观察者模式是一种行为设计模式,其中对象(主体)维护其依赖者(观察者)的列表,并自动通知它们任何状态更改。
此模式可确保在发生某些状态更改时通知多个对象。它广泛用于实现分布式事件处理系统。
观察者模式将主体与其观察者解耦,并允许动态添加或删除观察者。
Java 中的方法
让我们设计一个在温度变化时发送通知,让显示屏对应做出变化的气象站。Java示例如下:
csharp
// Observer Interface:
public interface Observer {
void update(float temperature);
}
// Subject Interface:
public interface Subject {
void registerObserver(Observer o);
void removeObserver(Observer o);
void notifyObservers();
}
// Concrete Subject:
public class WeatherStation implements Subject {
private float temperature;
private List<Observer> observers = new ArrayList<>();
public void setTemperature(float temperature) {
this.temperature = temperature;
notifyObservers();
}
public void registerObserver(Observer o) {
observers.add(o);
}
public void removeObserver(Observer o) {
observers.remove(o);
}
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(temperature);
}
}
}
// Concrete Observer:
public class Display implements Observer {
private String displayId;
public Display(String id) {
this.displayId = id;
}
public void update(float temperature) {
System.out.println(displayId + ": Temperature updated: " + temperature);
}
}
// Client:
public class WeatherApp {
public static void main(String[] args) {
WeatherStation station = new WeatherStation();
Display display1 = new Display("Display 1");
Display display2 = new Display("Display 2");
station.registerObserver(display1);
station.registerObserver(display2);
station.setTemperature(30f);
}
}
在此Java 示例中,WeatherStation
是Subject,Display
是在温度变化时更新的观察者。当站点温度发生变化时,两者都会显示display1
并display2
收到通知 ( )。update(float temperature)
Java 8+ 中的函数式方法
您可以使用Java 8+ 函数式特性来简化观察者模式,并使用函数式接口和 Java 的 lambda 表达式实现非常相似的方法。
以下是如何调整的示例:
java
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class WeatherStation {
private float temperature;
private List<Consumer<Float>> onTemperatureChangeListeners = new ArrayList<>();
public void setTemperature(float temperature) {
this.temperature = temperature;
notifyTemperatureChange(temperature);
}
private void notifyTemperatureChange(float newTemperature) {
onTemperatureChangeListeners.forEach(listener -> listener.accept(newTemperature));
}
public void onTemperatureChange(Consumer<Float> listener) {
onTemperatureChangeListeners.add(listener);
}
}
// Usage:
WeatherStation station = new WeatherStation();
// Registering listeners using lambda expressions:
station.onTemperatureChange(temp -> System.out.println("Display 1: Temperature updated to " + temp));
station.onTemperatureChange(temp -> System.out.println("Display 2: Temperature updated to " + temp));
// Simulating a temperature change:
station.setTemperature(30f);
在这个Java示例中:
- 该类
WeatherStation
维护一个对象列表Consumer<Float>
,这些对象是 Java 中可与 lambda 表达式一起使用的函数接口。 - 该
onTemperatureChange
方法允许注册Consumer
lambda 表达式,当温度变化时将调用该表达式。 - 当
setTemperature
被调用时,它会触发notifyTemperatureChange
,它会使用新的温度执行所有已注册的 lambda 表达式。
Kotlin 的方法:
Kotlin 提供观察者委托功能。Delegates.observable()
简化了对象属性更改的观察者模式实现:
您可以组合观察者委托来观察属性更改和高阶函数来注册回调。
kotlin
import kotlin.properties.Delegates
class WeatherStation {
// Observable property with callbacks:
var temperature: Float by Delegates.observable(0f) { _, _, newValue ->
onTemperatureChangeListeners.forEach { it(newValue) }
}
// List of callbacks:
private val onTemperatureChangeListeners = mutableListOf<(Float) -> Unit>()
// Function to add callbacks:
fun onTemperatureChange(listener: (Float) -> Unit) {
onTemperatureChangeListeners.add(listener)
}
}
// Client:
fun main() {
val station = WeatherStation()
// Registering callbacks:
station.onTemperatureChange { println("Display 1: Temperature updated to $it") }
station.onTemperatureChange { println("Display 2: Temperature updated to $it") }
// Simulating temperature change:
station.temperature = 30f
}
在这个Kotlin实现中:
temperature
中的属性 是WeatherStation
可观察属性。当它改变时,所有注册的回调onTemperatureChangeListeners
都会被调用。- 该
onTemperatureChange
方法允许注册对温度变化做出反应的 lambda 表达式(回调)。 - 客户端注册回调
WeatherStation
,每当属性更改时就会执行回调temperature
。
这种方法的好处:
- 简单性: 这种方法通过消除对接口和具体观察者类的需求来简化观察者模式。
- 灵活性: 很容易在运行时动态添加或删除行为(回调)。
- 表现力: 利用 Kotlin 的语言功能可以生成更具可读性和可维护性的代码。
Kotlin 特性简化了观察者模式
- 高阶函数和 Lambda: 使用函数(行为)作为参数来实现简洁的观察者实现。
- 委托属性 (
Delegates.observable()
): 简化属性更改观察。
KotlinDelegates.observable()
提供了传统观察者模式的简洁而强大的替代方案,特别是对于简单的用例。对于更复杂的场景,标准实现还是有一定作用的.