目录
前言
当一个对象与其它对象紧密关联,如果直接引用的话可能导致紧密耦合,如何描述这种一对多的关联关系?本文的观察者模式是一种思路。
1 定义
Observer(观察者)模式:定义对象间的一种一对多的依赖关系,当对象发生状态变化,依赖它的所有对象都将收到通知并自动改变。
2 适用性
- 当一个抽象模型有两方面,一个依赖另一个,同时又希望它们独立变化,不紧耦合。
- 当一个对象改变影响多个对象,同时又不清楚具体多少对象受影响。
- 一个对象改变必须通知其它对象,同时不希望这些对象紧密耦合。
3 结构
3.1 结构图
观察者模式结构图:
3.2 参与者
- Subject:目标对象,知道观察者,拥有添加删除观察者的接口方法。
- Observer:观察者,当目标发生变化时需要进行更新操作。
- ConcreteSubject:具体目标对象,维护观察者集合,在状态发生变化时通知观察者。
- ConcreteObserver:具体观察者,维持一个目标对象指针(也可以没有,只能被动接受通知信息);实现更新接口。
4 应用举例
以java定义的观察者模式:Observer接口和Observable类为例。定义一个时间更新订阅推送测试。
4.1 Subject——Observable
定义如下:
主要时定义了一个vector维护观察者对象和添加删除通知观察者的方法。
4.2 ConcreteSubject——ClockSubject
定义如下:
/**
* 目标对象
*/
@Data
@NoArgsConstructor
@Component
public class ClockSubject extends Observable {
/**
* 保存时间
*/
private LocalDateTime localDateTime;
/**
* 5秒执行一次
*/
@Scheduled(fixedDelay = 5000)
public void changedData(){
this.setChanged();
setLocalDateTime(LocalDateTime.now());
show();
this.notifyObservers();
}
public void show() {
System.out.println("5s推送一次时间:"+localDateTime);
}
}
定义一个更改状态定时更新方法。
4.3 Observer——Observer
接口定义如下:
主要定义了更新方法
4.4 ConcreteObserver——ObserverOne、ObserverTwo
这两个定义类似,以ObserverOne为例:
/**
* 观察者1
*/
@Component
public class ObserverOne implements Observer {
/**
* 只能被动更新,执行action操作,只接受ClockSubject目标
* @param o 目标
* @param arg 变化的参数
*/
@Override
public void update(Observable o, Object arg) {
if (o instanceof ClockSubject) {
action((ClockSubject) o);
} else {
System.out.println("忽略该观察者");
}
}
public void action(ClockSubject target) {
System.out.println("ObserverOne收到时间改变通知,做出行动,打印时间:"+target.getLocalDateTime());
}
}
更新方法就是判断是否是需要的目标,是的话就是执行action。
4.5 测试程序——Client
测试如下:
执行结果如下:
5 总结
当多个对象依赖一个其它对象比如,依赖一个数据状态时,可以建立这种一对多的关系,如果涉及的目标和观察者较多,可以考虑借助Mediator中介模式来管理目标和观察者。
参考文献
[1]. 《设计模式》