观察者模式(Observer Pattern)也称为发布-订阅模式(Publish-Subscribe Pattern),是很常用的设计模式之一。它是对象行为型模式的一种,可以让一些观察者对象看到你对象修改状态,以便它们能够作出响应。
观察者模式在不同的编程语言和版本中有不同的实现方式。本文将介绍如何在Java和JavaScript中使用观察者模式,并分析它们的特点和优劣。
Java中的观察者模式
Java中的观察者模式很容易实现,通过接口和类的组合来达到观察者和被观察者之间的耦合。被观察者将状态改变时,通知所有它所维护的观察者对象,让它们可以更新自己的状态。
下面是Java中Observer和Observable接口以及实现了观察者和被观察者的示例代码:
```
import java.util.Observable;
import java.util.Observer;
public class WeatherData extends Observable {
private float temperature;
private float humidity;
private float pressure;
public void measurementsChanged() {
setChanged();
notifyObservers();
}
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
}
public class CurrentConditionsDisplay implements Observer {
private float temperature;
private float humidity;
private float pressure;
public void update(Observable obs, Object arg) {
if (obs instanceof WeatherData) {
WeatherData weatherData = (WeatherData)obs;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
this.pressure = weatherData.getPressure();
display();
}
}
public void display() {
System.out.println("Current conditions: " + temperature
+ "F degrees and " + humidity + "% humidity and " + pressure + "hPa pressure");
}
}
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay();
weatherData.addObserver(currentDisplay);
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78, 90, 29.2f);
}
}
```
在上述代码中,WeatherData类实现了Observable接口,它维护了一个观察者对象列表,并提供了添加、删除和通知观察者对象的方法。该类定义了measurementsChanged方法,这个方法被调用时,会将Observable实例的changed标识设置为true,表示这个Observable实例的状态已经发生了变化,需要通知所有观察者。然后通过调用notifyObservers方法,通知在观察者列表中的所有观察者。
CurrentConditionsDisplay类实现Observer接口,它实现了update方法,它会在被观察者状态发生变化时被调用。可以在update方法中获取被观察者的状态,并更新自己的状态。display方法用来显示当前的天气状况。
优点:
1. Java中的观察者模式很容易实现,通过接口和类的组合来达到观察者和被观察者之间的耦合。
2. 观察者和被观察者之间的关系是松耦合的,被观察者不需要知道观察者的实现细节。
缺点:
1. 当被观察者有多个状态需要通知时,需要频繁的调用notifyObservers方法,可能会影响性能。
2. 在使用Java的观察者模式时,需要重写被观察者的notifyObservers方法,并手动调用setChanged,容易出错。
JavaScript中的观察者模式
JavaScript中的观察者模式也是很容易实现的,在ES6之前,可以通过函数和对象的组合来达到观察者和被观察者之间的耦合,并且不需要重写notifyObservers方法。
下面是通过函数和对象实现观察者模式的示例代码:
```
let observer = {
update: function(subject) {
console.log(`temperature is: ${subject.temperature}`);
}
};
function Subject() {
this.observers = [];
this.temperature = 0;
}
Subject.prototype.addObserver = function(observer) {
this.observers.push(observer);
}
Subject.prototype.removeObserver = function(observer) {
let index = this.observers.indexOf(observer);
if (index >= 0) {
this.observers.splice(index, 1);
}
}
Subject.prototype.notifyObservers = function() {
for (let i = 0; i < this.observers.length; i++) {
let observer = this.observers[i];
observer.update(this);
}
}
Subject.prototype.setTemperature = function(temperature) {
this.temperature = temperature;
this.notifyObservers();
}
let subject = new Subject();
subject.addObserver(observer);
subject.setTemperature(70);
subject.setTemperature(80);
```
在上述代码中,Subject类维护了一个观察者对象列表,并提供了添加、删除和通知观察者对象的方法。当设置温度时,会自动通知所有在观察者列表中的观察者。
Observer对象有一个update方法,它会在Subject状态发生变化时被调用。可以在update方法中获取被观察者的状态,并更新自己的状态。
优点:
1. 在JavaScript中使用观察者模式,可以通过函数和对象的组合来达到观察者和被观察者之间的耦合。
2. 可以直接调用notifyObservers方法通知所有观察者,不需要重写该方法,并手动设置changed标识。
缺点:
1. JavaScript中的观察者模式无法像Java那样为观察者和被观察者之间实现松耦合。
2. 在JavaScript中任何对象都可以成为观察者,没有像Java中的Observer接口那样的约束。
从上面的讨论可以看到,观察者模式在不同的编程语言和版本中有不同的实现方式,使用时需要根据实际情况和语言特点来选择最佳的实现方式。总体来说,观察者模式是一种非常实用且灵活的设计模式,在实现事件通知和消息传递方面有很广泛的应用。
扫码咨询 领取资料