一、基本介绍
观察者模式是一种对象行为模式。它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。在观察者模式中,主题是通知的发布者,它发出通知时并不需要知道谁是它的观察者,可以有任意数目的观察者订阅并接收通知。观察者模式不仅被广泛应用于软件界面元素之间的交互,在业务对象之间的交互、权限管理等方面也有广泛的应用。
—— 引用自百度百科
二、模式的定义与特点
观察者(Observer)模式的定义:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。
- 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
- 目标与观察者之间建立了一套触发机制。
它的主要缺点如下:
- 目标与观察者之间的依赖关系并没有完全解除,而且有可能出现循环引用。
- 当观察者对象很多时,通知的发布会花费很多时间,影响程序的效率。
三、模式的结构与实现
实现观察者模式时要注意具体目标对象和具体观察者对象之间不能直接调用,否则将使两者之间紧密耦合起来,这违反了面向对象的设计原则。 观察者模式的主要角色如下:
四、具体实现步骤
相关场景描述:
某天的下午,班主任通知某班学生和老师将要听一节课,以此来对老师的授课质量进行评分。老师和学生收到后开始安排相关的课程。上课期间老师和班主任通过观察学生的神情来预判课程的讲的好坏,老师观察到学生皱眉头可以适当调节课程气氛,班主任观察到学生课堂氛围好转,给与高分。课程结束后,班主任和老师回到办公室,一起回顾这节开心的课程。
①使用自定义的方式实现观察者模式
1.构建一个课程实体类(以下均省略Setter和Getter)
1 |
|
2.构建一个发现者的抽象类以及相关的实现类,老师和班主任都分别继承了该接口并重写相关方法,
1 |
|
老师拿着教材开始来上课:
1 |
|
班主任来听课:
1 |
|
这时候轮到我们学生的主体登场了:
1 |
|
学生主体,被观察的对象:
1 |
|
那么我们焦急万分等待课程终于如期进行了,开始记录报告吧:
1 |
|
回到办公室的老师和班主任都眉开眼笑,学生对这节课也是很满意,可以看到如下的报告回顾:
1 |
|
②使用JDK提供的类实现观察者模式
这里我们可以使用JDK的类来实现相关的观察模式,自带的观察者的类有Observer接口和Observable类,使用这两个类中的方法可以很好的完成观察者模式,而且JDK帮我们做了相关的加锁操作,保证了线程安全,整体来说会对我们上面的类进行改进和简化操作。
我们主要需要改造的是被观察的主体和实现观察者的类,如下所示:
1 |
|
运行效果如下:
1 |
|
划重点:
这里Observer内部只定义了一个方法,主要用于在被观察的对象发出通知后做出相应的动作:
update(Observable o, Object arg);
Observable类中的方法有:
addObserver(添加观察者)、deleteObserver(删除观察者)、notifyObservers(唤醒所有的观察者,可带入参数)、deleteObservers(删除所有观察者)、setChanged(改变标志为True)、clearChanged(改变标志为false)、hasChanged(查看标志状态)、countObservers(统计观察者个数)
这些方法中有些加了同步机制保证线程安全,我们可以根据需要使用提供的已有相关方法,增强代码的复用性。有兴趣的可以看下源码的实现,这里就不再累述。
五、总结
观察者模式的让我们知道了在设计开发的时候一定要“多用组合,少用继承”。
我们设计开发是应该是针对接口变成,而不针对实现编程。
这是一种创建松散耦合代码的技术。它定义对象间 一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。由主体和观察者组成,主体负责发布事件,同时观察者通过订阅这些事件来观察该主体。主体并不知道观察者的任何事情,观察者知道主体并能注册事件的回调函数。