【观察者模式】
也叫作发布/订阅模式,使用较为频繁。
定义了对象间一种一对多的依赖关系,当一个对象改变状态时,则所有依赖于它的对象都会得到通知并被自动更新。
观察者模式由以下几个角色组成:
* Subject 被观察者
定义被观察者必须实现的职责,他必须能够动态地增阿基、取消观察者。一般是抽象类或实现类,仅仅完成作为被观察者必须实现的职责:管理观察者+通知观察者。
* ConcreteSubject具体的被观察者
定义观察者自己的业务逻辑,同时定义对哪些事件进行通知。
* Observer 观察者
观察者接收到消息后,即进行update(更新方法)操作,对接收到的消息进行处理。
* ConcreteObserver具体的观察者
每个具体观察者在接受到消息后的处理反应是不一样的,各个观察者有自己的处理逻辑。
【观察者模式 例子】
package com.Higgin.Observer; import java.util.ArrayList; import java.util.List; /** * 电视观众接口 */ interface Viewer{ public void feel(String show); } /** * 年轻观众 */ class YongViewer implements Viewer{ @Override public void feel(String show) { System.out.println("年轻人:感觉《"+show+"》很棒!"); } } /** * 老年观众 */ class OldViewer implements Viewer{ @Override public void feel(String show) { System.out.println("老年人:感觉《"+show+"》一般!"); } } /** * 抽象电视节目 */ abstract class TVProgrammer{ //用来保存 注册的电视观众对象 private List<Viewer> viewers=new ArrayList<Viewer>(); //注册一个电视观众 public void attach(Viewer v){ this.viewers.add(v); } //删除一个电视观众 public void detach(Viewer v){ this.viewers.remove(v); } //通知所有注册的电视观众 public void notifyViewers(String show){ for(Viewer v:viewers){ v.feel(show); } } } /** * 具体的娱乐电视节目 */ class HappyTVProgrammer extends TVProgrammer{ //切换不同的娱乐节目 public void change(String newShow){ super.notifyViewers(newShow); //调用父类的通知方法 } } public class TestObserver { public static void main(String[] args) { Viewer yong=new YongViewer(); //一个年轻观众 Viewer old=new OldViewer(); //一个老年观众 HappyTVProgrammer tvp=new HappyTVProgrammer(); //娱乐电视节目 tvp.attach(yong); //注册一个年轻人 tvp.attach(old); //注册一个老年人 tvp.notifyViewers("极限挑战"); System.out.println("============================="); tvp.detach(old); //老人不爱看,解除 tvp.change("奔跑吧,兄弟!"); } }
【运行结果】
【观察者模式 优点】
* 观察者和被观察者之间是抽象耦合的
不管是增加观察者还是被观察者都非常容易,而且在java中已经实现了抽象层级的定义,在系统扩展方面应用良好。
* 建立了一套触发机制
根据单一职责原则,每个类的职责是单一的,如A事件触发B事件,B事件触发C事件...这是一个触发机制,形成一个触发链,观察者模式可以实现这里的链条形式。
【观察者模式 缺点】
要考虑开发效率和运行效率的问题,一个被观察者,多个观察者,开发和调试较为复杂,而且在JAVA中消息通知默认是顺序执行的,一个观察者卡壳,会影响整体的执行效率。这种情况一般会采用异步的方式。
【观察者模式 使用场景】
* 关联行为场景,注意关联行为是可拆分的,而不是“组合”关系。
* 事件多级触发场景。
* 跨系统的消息交换场景。