最近小Y在看《反黑》这部剧,最引人回味的是堪称经典的山鸡哥飞上枝头变凤凰,当初的古惑仔弃暗投明做警察,可谓是涅槃重生啊。
张sir:山鸡,和兴盛最近很嚣张啊,该是你大展身手的时候了,你要以最短时间打入他们内部获取犯罪证据,同时你要更名为凤凰,UnderStand?
凤凰仔:Yes,Sir。
经过一段时间潜伏,凤凰哥终于打入和兴盛内部,成为韩彬的一把手。时刻监视着大佬们的一举一动。
凤凰仔:张sir,和兴盛大佬们齐聚一起,准备搞场大龙凤,你立马拖班人马过来压压惊,顺便来了一锅端。
根据凤凰监提供的证据,警方成功把这个社团搞得鸡飞狗跳。最后凤凰仔用枪指着韩彬的头来了一句:一直在你身边的警察,是我。来了一个一百八十度的转弯,山鸡变凤凰。
凤凰哥、Laughing哥是港剧卧底的佼佼者,让人赞不绝口。在设计模式中,照样有充当这样角色的存在——观察者模式。
一、基本概念
1.定义
观察者模式也叫做发布订阅模式,定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。
2.角色介绍
Subject被观察者
定义被观察者必须实现的职责,它必须能够动态地增加、取消观察者。它一般是抽象类或者是实现类,仅仅完成作为被观察者必须实现的职责:管理观察者并通知观察者。Observer观察者
观察者接收到消息后,即进行update(更新方法)操作,对接收到的信息进行处理。ConcreteSubject具体的被观察者
定义被观察者自己的业务逻辑,同时定义对哪些事件进行通知。ConcreteObserver具体的观察者
每个观察在接收到消息后的处理反应是不同,各个观察者有自己的处理逻辑。
3.观察者模式的使用场景
- 跨系统的消息交换场景,如消息队列的处理机制。
- 关联行为场景。需要注意的是,关联行为是可拆分的,而不是“组合”关系。
- 事件多级触发场景。
二、观察者模式演绎山鸡变凤凰
在反黑组在监视这几位大佬的同时,商业调查科等等其他警察部门也在监视着,为了使各部门行动统一,凤凰仔收集到的证据统一使用,根据其反馈回来的消息,各部门做相应的准备。
1.具体角色分配UML
2.代码实现
①和兴盛的抽象被观察者
public abstract class HeXingSheng {
//保存监视和兴的警察部门
private List<Police> polices=new ArrayList<>();
//增加监听的警察部门
public abstract void addPoliceObserver(Police police);
//删除监听的警察部门
public abstract void deletePoliceObserver(Police police);
//通知每个监听部门作出反应
public abstract void notifyPolices(String tip);
}
②和兴盛大佬们的具体被观察类
public class HeadOfGang extends HeXingSheng {
@Override
public void addPoliceObserver(Police police) {
this.polices.add(police);
}
@Override
public void deletePoliceObserver(Police police) {
this.polices.remove(police);
}
@Override
public void notifyPolices(String tip) {
for(Police police:polices){
police.action(tip);
}
}
}
③警察部门的抽象观察者
public abstract class Police {
//根据信息作出反应
public abstract void action(String action);
}
④反黑组
public class FanHeiTeam extends Police {
@Override
public void action(String action) {
System.out.println("卧底凤凰提供的情报:"+action);
System.out.println("反黑组根据情报对和兴盛进行相关黑社会行为进行控告。");
}
}
⑤商业调查科
public class ShangYeTeam extends Police{
@Override
public void action(String action) {
System.out.println("卧底凤凰提供的情报:"+action);
System.out.println("商业调查科根据情报对和兴盛进行相关商业行为进行控告。");
}
}
⑥Client
public class Client {
public static void main(String[] args) {
//被观察的对象-和兴盛
HeXingSheng xingSheng=new HeadOfGang();
//观察对象-反黑组、商业调查科
Police fanHeiTeam=new FanHeiTeam();
Police shangye=new ShangYeTeam();
//增加观察者
xingSheng.addPoliceObserver(fanHeiTeam);
xingSheng.addPoliceObserver(shangye);
//凤凰仔收集到证据,通知各部门准备行动
xingSheng.notifyPolices("和兴盛大佬们聚在一起搞龙凤。");
}
}
输出的结果为:
//反黑组
卧底凤凰提供的情报:和兴盛大佬们聚在一起搞龙凤。
反黑组根据情报对和兴盛进行相关黑社会行为进行控告。
//商业调查科
卧底凤凰提供的情报:和兴盛大佬们聚在一起搞龙凤。
商业调查科根据情报对和兴盛进行相关商业行为进行控告。
三、观察者模式优缺点
1.优点
- 观察者模式支持广播通信。被观察者会向所有的登记过的观察者发出通知。
- 观察者和被观察者之间是抽象耦合。则不管是增加观察者还是被观察者都非常容易扩展,而且在Java中都已经实现的抽象层级的定义,在系统扩展方面更是得心应手。
2.缺点
如果一个被观察者对象有很多直接和间接的观察者的话,将所有的观察者都通知到会花费很多时间,效率让人担忧。
一个被观察者,多个观察者,开发和调试就会比较复杂,而且在Java中消息的通知默认是顺序执行,一个观察者卡壳,会影响整体的执行效率。在这种情况下,一般考虑采用异步的方式。
四、总结
观察者模式在项目中非常常用,但是从上面页面知道观察者模式也相对存在着缺点,一是广播链的问题。另外一个就是异步处理问题,在开发中需要格外注意。