一、类型
行为类模式
二、定义
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖它的对象都会得到通知并自动更新。
三、参与者
1、Subject(目标接口):目标就是观察者观察的对象,它拥有一个集合来存放观察者对象,并提供注册、删除、通知观察者对象的接口。
2、ConcreteSubject(具体的目标类):实现 Subject 接口或抽象类,当有数据更新时,向各个观察者发送通知。
3、Observer(观察者):一般是一个接口,当目标状态发生变化时,会调用观察者中相应的更新接口。
4、ConcreteObserver(具体的观察者):观察者接口的具体实现,主要是定义目标发生变化时所要处理的逻辑。
四、类图
五、示例
举例
现在有一个气象站类 WeacherData
,主要用于收集并更新 温度
,然后将数据通知给两个气象网站用于展示。现使用观察者模式将其实现。
代码
- Observer:观察者的接口,有一个 update 方法。
// 观察者 接口
public interface Observer {
// 当目标类的数据发生变化时,就会调用这个接口通知观察者
void update(float temperature);
}
- ConcreteObserverA:观察者接口的具体实现类
// 观察者接口的实现类A
public class ConcreteObserverA implements Observer {
// 温度
private float temperature;
@Override
public void update(float temperature) {
this.temperature = temperature;
System.out.println("A网站提醒您,现在的温度为:" + temperature);
}
// get、set、toString方法
}
- ConcreteObserverB:观察者接口的具体实现类
// 观察者接口的实现类B
public class ConcreteObserverB implements Observer {
// 温度
private float temperature;
@Override
public void update(float temperature) {
this.temperature = temperature;
System.out.println("B网站提醒您,现在的温度为:" + temperature);
}
// get、set、toString方法
}
- Subject:目标接口
// 目标 接口
public interface Subject {
// 1、添加观察者
void addObserver(Observer o);
// 2、删除观察者
void deleteObserver(Observer o);
// 3、通知观察者
void notifyObservers();
}
- WeatherData:气象站类,实现目标接口
// 天气数据,继承目标类
public class WeatherData implements Subject {
// 温度
private float tempereture;
// 用于存放观察者的集合
private List<Observer> list = new ArrayList<>();
// 提供修改 温度 的方法
public void changeData(float tempereture) {
// 1、修改本地数据
this.tempereture = tempereture;
// 2、通知观察者
this.notifyObservers();
}
@Override
public void addObserver(Observer o) {list.add(o);}
@Override
public void deleteObserver(Observer o) {list.remove(o);}
@Override
public void notifyObservers() {
// 遍历观察者集合,并将最新的 temperature 数据推送过去
for (Observer o : list) {
o.update(this.tempereture);
}
}
}
- Client:客户端
public class Client {
public static void main(String[] args) {
// 创建一个 目标类
WeatherData weatherData = new WeatherData();
// 创建两个 观察者
ConcreteObserverA concreteObserverA = new ConcreteObserverA();
ConcreteObserverB concreteObserverB = new ConcreteObserverB();
// 将 观察者 放入 目标类 的集合中
weatherData.addObserver(concreteObserverA);
weatherData.addObserver(concreteObserverB);
// 修改 数据,目标类将会通知观察者,然后观察者打印数据
weatherData.changeData(10);
}
}
- 执行结果
A网站提醒您,现在的温度为:10.0
B网站提醒您,现在的温度为:10.0
六、注意事项和细节
- 优点:观察者模式会使用一个集合来管理用户,增加观察者时,无需修改核心类( WeatherData),遵守开闭原则(对拓展开放,对修改关闭)。
- 缺点:观察者模式是一种常用的触发机制,它形成一条触发链,依次对各个观察者的方法进行处理。但是当观察者太多时,会有性能问题。