目录
1. 观察者模式
1.1 定义、优缺点、适用场景
- 1. 观察者模式
- 1.1 定义、优缺点、适用场景
- 1.2 模式的结构与实现
定义:对象之间多(Observer)对一(Subject)依赖的一种设计方案,被依赖的对象为Subject,依赖的对象为Observer,Subject通知Observer变化
优点:
- 以集合的方式来管理用户(Observer),可以动态的添加和删除观察者,满足开闭原则
- 数据更新时可以及时的通知观察者
缺点:
- 如果观察者很多,所有的观察者都通知会花费很多时间
- 观察者模式没有相应的机制使观察者知道所观察的对象是怎么发生变化的
适用场景:
- 对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变
- 对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节
结构:
- 观察者接口(Observer):为所有的具体观察者定义一个接口,在得到主题的通知时更新自己
- 具体观察者(ConcreteObserver):实现抽象观察者所要求的更新接口,以便使本身的状态与主题的状态相协调
- 主题(Subject):规定了具体主题需要实现的方法,比如添加、删除观察者以及通知观察者更新数据的方法
- 具体主题(ConcreteSubject):具体主题是实现主题接口类的一个实例,该实例包含有经常发生变化的数据。具体主题需使用一个集合比如ArrayList,存放观察者的引用,以便数据变化时通知具体观察者
实现:
天气预报项目:气象局进行温度、湿度等监测,同时将这些数据开放给第三方天气机构。气象局可以动态的添加和删除第三方天气机构,气象局的数据更新也能立刻推送给第三方天气机构
import java.util.ArrayList;
public class ObserverTest {
public static void main(String[] args) {
// 创建一个气象局
WeatherSubject weatherSubject = new WeatherSubject();
// 创建观察者
Observer baiduObserver = new BaiduObserver();
// 将第三方天气机构注册到气象局
weatherSubject.registerObserver(baiduObserver);
// 更新天气数据,并推送给各个observer
System.out.println("======第一次通知各个注册的观察者======");
weatherSubject.setData(20f, 20.6f);
// 动态的添加和删除observer
Observer mojiObserver = new MojiObserver();
weatherSubject.registerObserver(mojiObserver);
weatherSubject.removeObserver(baiduObserver);
System.out.println("======第二次通知各个注册的观察者======");
weatherSubject.setData(30f, 30.6f);
}
}
// 观察者接口-第三方天气机构
abstract class Observer {
protected float temperature;
protected float humidity;
// 气象局通过调用该方法(推送方式),进行温度和湿度的更新
public void update(float temperature, float humidity) {
this.temperature = temperature;
this.humidity = humidity;
// 更新的同时,进行展示
this.display();
}
// 每个观察者,展示天气数据的方式不一样
public abstract void display();
}
// 具体观察者-百度天气
class BaiduObserver extends Observer {
public void display() {
System.out.println("======百度天气======");
System.out.println("******温度: " + this.temperature + "******");
System.out.println("******湿度: " + this.humidity + "******");
}
}
// 具体观察者-墨迹天气
class MojiObserver extends Observer {
public void display() {
System.out.println("======墨迹天气======");
System.out.println("******温度: " + this.temperature + "******");
System.out.println("******湿度: " + this.humidity + "******");
}
}
// 主题接口
interface Subject {
public void registerObserver(Observer observer);
public void removeObserver(Observer observer);
public void notifyObservers();
}
// 具体主题-气象局
class WeatherSubject implements Subject {
// 最新的温度和湿度
private float temperatrue;
private float humidity;
// 观察者集合,进行统一的管理
private ArrayList observers;
public WeatherSubject() {
observers = new ArrayList();
}
// 当气象局数据有数据更新时,更新完数据时,再推送给各个observer
public void setData(float temperature, float humidity) {
this.temperatrue = temperature;
this.humidity = humidity;
this.notifyObservers();
}
// 注册一个观察者
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
// 移除一个观察者
@Override
public void removeObserver(Observer observer) {
if (observers.contains(observer)) {
observers.remove(observer);
}
}
// 遍历所有的观察者,并将天气情况推送给observer
@Override
public void notifyObservers() {
for (int i = 0; i < observers.size(); i++) {
observers.get(i).update(this.temperatrue, this.humidity);
}
}
}
运行程序,结果如下:
======第一次通知各个注册的观察者======
======百度天气======
******温度: 20.0******
******湿度: 20.6******
======第二次通知各个注册的观察者======
======墨迹天气======
******温度: 30.0******
******湿度: 30.6******