是一种常用的设计模式,它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当主题对象状态发生变化时,它的所有观察者都会收到通知并且自动更新。
在观察者模式中,主题对象通常被称为“被观察者”(Observable)或 “主体” (Subject),而观察者对象通常被称为“观察者”(Observer)或 “订阅者”(Subscriber)。主题对象维护一个观察者列表,当它的状态发生变化时,会遍历这个列表并通知所有的观察者。
观察者模式的优点:
观察者模式将主题对象和观察者对象解耦,它们之间只依赖于抽象接口,而不是具体的实现。
可以通过添加新的观察者对象来扩展系统,而不需要修改主题的代码。
观察者模式可以在运行时动态地添加或删除观察者对象,使得系统更加灵活。
在现实生活中,我们经常会从手机、电脑、电视等途径关注天气。假设有一个气象站,它会定期更新当前的天气情况,并且希望通知所有的观察者(比如手机端、电视端、网站端等)。
首先我们定义一个主题接口Subject,它包含添加、删除和通知观察者的方法:
package com.obser;
/**
* @author evanYang
* @since 2023/6/6 2:34 PM
*/
public interface Subject {
void registerObserver(Observer observer);
void removeOberver(Observer observer);
void notifyObserver();
}
接下来,我们定义一个具体的主题类 WeatherData,它实现了 Subject 接口,并且包含了当前天气情况的数据:
package com.obser;
import java.util.ArrayList;
import java.util.List;
/**
* @author evanYang
* @since 2023/6/6 2:41 PM
*/
public class WeatherData implements Subject{
private float temperature;
private float humidity;
private float pressure;
private List<Observer> observers;
public WeatherData() {
this.observers = new ArrayList<>();
}
public void setMeasurements(float temperature,float humidity,float pressure) {
this.temperature=temperature;
this.pressure=pressure;
this.humidity=humidity;
notifyObserver();
}
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeOberver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObserver() {
for (Observer observer : observers) {
observer.update(temperature,humidity,pressure);
}
}
}
其中,WeatherData 类维护了一个观察者列表 observers,并且在数据发生变化时调用 notifyObservers() 方法通知所有观察者。
接下来,我们定义一个观察者接口 Observer,它包含了一个更新方法 update():
package com.obser;
/**
* @author evanYang
* @since 2023/6/6 2:35 PM
*/
public interface Observer {
void update(float temperature,float humidity,float pressure);
}
最后,我们定义一个具体的观察者类 PhoneDisplay,它实现了 Observer 接口,并且在接收到通知后更新显示:
package com.obser;
/**
* @author evanYang
* @since 2023/6/6 2:48 PM
*/
public class PhoneDisplay implements Observer{
private float temperature;
private float humidity;
private float pressure;
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
display();
}
public void display() {
System.out.println("currency conditions: "+ temperature + "F degress and " + humidity + "%humidity and "
+ pressure + "Pa pressure" );
}
}
现在,我们可以创建一个 WeatherData 对象,并且添加一个 PhoneDisplay 观察者,然后模拟天气数据的变化:
package com.obser;
/**
* @author evanYang
* @since 2023/6/6 2:52 PM
*/
public class MainDemo {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
PhoneDisplay display = new PhoneDisplay();
weatherData.registerObserver(display);
weatherData.setMeasurements(80,20,33);
weatherData.setMeasurements(50,22,11);
weatherData.setMeasurements(66,22,11);
}
}