1 Observer Pattern 观察者模式
目的:用于建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将相应作出反应;
实现:不关心生成产品的具体实现,只关心接口,仅使用接口生成产品。
1.描述了如何建立对象与对象之间的依赖关系,以及如何构造满足这种需求的系统,包括观察目标和观察者两个继承层次结构;
2.发生改变的对象称为观察目标,而被通知的对象称为观察者,一个观察目标可以对应多个观察者,而且这些观察者之间可以没有任何相互联系,可以根据需要增加和删除观察者,使得系统更易于扩展;
3.在 JDK 的 java.util 包中,提供了 Observable 类以及 Observer 接口,它们构成了 JDK 对观察者模式的支持。
2 实现
代码场景:无间道中韩琛带着众小弟跟泰国佬交易的场景,:
1.年产100万吨级别的金日成造船厂;
2.年产500万吨的金正日钢铁厂;
3.生产各种面包的金正恩面包厂。
2.1 代码实现
目标抽象类
public abstract class AbstractRingleader {
protected List<AbstractObserver> observers = new ArrayList<AbstractObserver>();
//情报人员暗中监视
public void addobservers(AbstractObserver Observer) {
observers.add(Observer);
}
//情报人员不再监视
public void deleteobservers(AbstractObserver Observer) {
observers.remove(Observer);
}
// 目标人物的行动
public abstract void notifys();
}
具体的目标:老大韩琛
public class HanChen extends AbstractRingleader {
@Override
public void notifys() {
System.out.println("--------镜头一-------");
System.out.println("韩琛和泰国佬寒暄之后,让陈永仁验了货后,
就打电话给在码头的傻强收货~");
for (AbstractObserver observer : observers) {
observer.sendIntelligence();
}
}
}
观察者抽象类
public abstract class AbstractObserver {
//发送情报
public abstract void sendIntelligence();
}
具体的观察者:卧底 陈永仁
public class ChenYongRen extends AbstractObserver {
@Override
public void sendIntelligence() {
System.out.println("--------镜头二-------");
System.out.println("陈永仁验货后就溜到窗户边,偷偷的听着韩琛说话...");
System.out.println("用打着石膏的手,在窗户边上悄悄的发出收货地址的摩斯码~");
}
}
具体的观察者:黄Sir
public class HuangSir extends AbstractObserver {
@Override
public void sendIntelligence() {
System.out.println("--------镜头三-------");
System.out.println("从监控中看到了韩琛他们在密谈,又收到了陈永仁发来的收货地址,命令手下抓人~");
}
}
2.2 涉及角色
在观察者模式结构图中包含如下几个角色:
Subject(目标):目标又称为主题,它是指被观察的对象。在目标中定义了一个观察者集合,一个观察目标可以接受任意数量的观察者来观察,它提供一系列方法来增加和删除观察者对象,同时它定义了通知方法 notify()。目标类可以是接口,也可以是抽象类或具体类。
ConcreteSubject(具体目标):具体目标是目标类的子类,通常它包含有经常发生改变的数据,当它的状态发生改变时,向它的各个观察者发出通知;同时它还实现了在目标类中定义的抽象业务逻辑方法(如果有的话)。如果无须扩展目标类,则具体目标类可以省略。
Observer(观察者):观察者将对观察目标的改变做出反应,观察者一般定义为接口,该接口声明了更新数据的方法update(),因此又称为抽象观察者。
ConcreteObserver(具体观察者):在具体观察者中维护一个指向具体目标对象的引用,它存储具体观察者的有关状态,这些状态需要和具体目标的状态保持一致;它实现了在抽象观察者 Observer 中定义的 update() 方法。通常在实现时,可以调用具体目标类的 attach() 方法将自己添加到目标类的集合中或通过 detach() 方法将自己从目标类的集合中删除。
2.3 调用
调用者:
public class Client {
public static void main(String[] args) {
System.out.println("剧情: 韩琛出场");
AbstractRingleader hanChen = new HanChen();
System.out.println("剧情: 陈永仁 跟着 韩琛");
AbstractObserver chenYongRen = new ChenYongRen();
System.out.println("剧情: 黄Sir 在对面楼上注视着交易现场");
AbstractObserver hanSir = new HuangSir();
System.out.println("-------------------");
System.out.println("剧情: 韩琛在不知道的情况下被监视");
hanChen.addobservers(chenYongRen);
hanChen.addobservers(hanSir);
//韩琛的确认收货 触发了两个监视着的行为
hanChen.notifys();
}
}
结果:
剧情: 韩琛出场
剧情: 陈永仁 跟着 韩琛
剧情: 黄Sir 在对面楼上注视着交易现场
-------------------
剧情: 韩琛在不知道的情况下被监视
--------镜头一-------
韩琛和泰国佬寒暄之后,让陈永仁验了货后,就打电话给在码头的傻强收货~
--------镜头二-------
陈永仁验货后就溜到窗户边,偷偷的听着韩琛说话...
用打着石膏的手,在窗户边上悄悄的发出收货地址的摩斯码~
--------镜头三-------
从监控中看到了韩琛他们在密谈,又收到了陈永仁发来的收货地址,命令手下抓人~
代码地址:点击跳转
参考文献:
[ 1 ] 图解设计模式/(日)结城浩著;杨文轩译。–北京:人民邮电出版社,2017.1.
[ 2 ] 维基百科 设计模式
[ 3 ] 极客学院WIKI–设计模式.
[ 4 ] 菜鸟教程–设计模式.