观察者模式(世界线的观测者)
定义
观察者模式(Observer Partern)也叫做发布/订阅模式(Publish/Subscribe),一种以监听为核心的设计模式。
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
优缺点、应用场景
优点
- 观察者和被观察者之间是抽象耦合。如此不论是增加观察者还是被观察者都非常容易拓展,而且都是Java中已经实现的抽象层级定义。
- 建立一套触发机制。蝴蝶效应,一举一动都会影响世界线的变动。
缺点
需要考虑开发和运行效率,一般会采用异步的方式。
应用场景
- 关联行为场景。关联行为是可拆分的,而不是耦合的"组合"关系
- 事件多级触发场景
- 跨系统的消息交换场景,如消息队列的上下游消息的传递。
代码模拟场景
战国时期秦国的丞相李斯想要监控韩非子的一举一动,于是安插间谍在韩非子周围
实验小结
- 将观察者嵌入到被观察者类中确实能够实现监控,但是不利于观察者的拓展
- 现需要两个接口Observer和Observable
- 前者是观察者实现的,需要重写update方法,决定监听到方法执行后的逻辑
- 后者是被观察者实现的,将所有参与观察的观察者封装成集合,执行方法时统一通知。
然后去欺骗世界吧,命运石之门必定存在,EL PSY CONGROO
观察者模式
UML图
观察者接口与实现类
java
/**
* 观察者接口
*/
public interface Observer {
// 被观察者操作则通知
public void update(String context);
}
public class LiSi implements Observer {
// 若韩非子有动向,立即知晓
@Override
public void update(String context) {
System.out.println("李斯:观察到韩非子活动,开始向上级汇报");
this.reportToEmperor(context);
System.out.println("李斯:汇报完毕。。\n");
}
private void reportToEmperor(String context) {
System.out.println("李斯:报~~~!韩非子有活动了----->" + context);
}
}
/**
* 张苍,同韩非子、李斯为荀子的弟子
* 助刘邦统一,官至丞相
*/
public class ZhangCang implements Observer {
@Override
public void update(String context) {
System.out.println("张苍:观察到韩非子活动,开始♂摸索");
jieBroQuotation(context);
System.out.println("张苍:摸索♂结束");
}
public void jieBroQuotation(String context) {
System.out.println("张苍:韩非子有活动?让我康康!!------->" + context);
}
}
被观察者接口及实现类
java
/**
* 被观察者接口
*/
public interface Observable {
// 增加一个观察者
public void addObserver(Observer observer);
// 删除一个观察者
public void deleteObserver(Observer observer);
// 被观察者操作时,通知观察者
public void notifyObservers(String context);
}
被观察者个性接口
java
/**
* 被观察者接口
*/
public interface IHanFeiZi {
// 韩非子吃早餐
public void haveBreakfast();
// 韩非子玩♂游♂戏
public void haveFun();
}
public class HanFeiZi implements Observable,IHanFeiZi {
// 所有的观察者放在一个集合中
private List<Observer> observerList = new ArrayList<>();
// 韩非子要吃饭了
@Override
public void haveBreakfast() {
System.out.println("韩非子:开始吃饭了。。。");
this.notifyObservers("韩非子在吃饭");
}
// 韩非子要玩♂游♂戏了
@Override
public void haveFun() {
System.out.println("韩非子:玩♂游♂戏");
this.notifyObservers("韩非子在玩♂游♂戏");
}
// 添加一个观察者
@Override
public void addObserver(Observer observer) {
this.observerList.add(observer);
}
// 删除一个观察者
@Override
public void deleteObserver(Observer observer) {
this.observerList.remove(observer);
}
// 通知观察者们
@Override
public void notifyObservers(String context) {
for (Observer observer : observerList) {
observer.update(context);
}
}
}
入口类方法
java
public static void realObserve() {
// 观察者阵容
Observer liSi = new LiSi();
Observer zhangCang = new ZhangCang();
// 被观察者
HanFeiZi hanFeiZi = new HanFeiZi();
hanFeiZi.addObserver(liSi);
hanFeiZi.addObserver(zhangCang);
// 被观察者开始动作
hanFeiZi.haveBreakfast();
hanFeiZi.haveFun();
}
结果
参考书籍
秦小波《设计模式之禅》