观察者模式(又被称为发布-订阅模式、模型-视图模式、源-收听者模式或从属者模式)
观察者模式中,一个目标对象管理所有依赖于它的观察者对象,并且在它本身的状态改变时主动发出通知。
应用场景
拍卖会可以认为是观察者模式的一种,每个投标人都可以出价。拍卖师开始拍卖时,他观察是否有牌子举起出价。每次接受一个新的出价都改变了拍卖的当前价格,并且广播给所有的投标人。
在JDK中的应用
java.util.EventListener
javax.servlet.http.HttpSessionBindingListener
javax.servlet.http.HttpSessionAttributeListener
javax.faces.event.PhaseListener
参与角色
抽象主题(Subject):
抽象主题提供一个接口,可以增加和删除观察者对象;
Subject把所有观察者对象的引用保存到一个集合里,每个主题都可以有任何数量的观察者;
具体主题(ConcreteSubject):
存储有关状态,这些状态应与目标的状态保持一致;
将有关状态存入具体观察者对象;
在具体主题内部状态改变时,给所有登记过的观察者发出通知;
实现Observer的更新接口以使自身状态与目标的状态保持一致。
抽象观察者(Observer):
为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
具体观察者(ConcreteObserver):
实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。
观察者模式的类图
观察者模式的意图是定义对象之间一对多的依赖关系,一个对象状态改变,其他相关联的对象就会得到通知并被自动更新。

观察者模式实例
在这个实例中,观察者能够注册此主题,任何在此主题上的内容提交导致的变化都会通知所有在注册的观察者。
Subject抽象主题:
1
2
3
4
5
6
7
8
9
10
11
12
<code>public</code> <code>interface</code> <code>Subject {</code>
<code> </code><code>//注册观察者</code>
<code> </code><code>public</code> <code>void</code> <code>attach(Observer obs);</code>
<code> </code><code>//移除观察者</code>
<code> </code><code>public</code> <code>void</code> <code>detach(Observer obs);</code>
<code> </code>
<code> </code><code>//通知观察者</code>
<code> </code><code>public</code> <code>void</code> <code>noticeObservers();</code>
<code> </code><code>//获得主题的更新信息</code>
<code> </code><code>public</code> <code>String getUpdate();</code>
<code>}</code>
Observer抽象订阅者:
<code>public</code> <code>interface</code> <code>Observer {</code>
<code> </code><code>/**</code>
<code> </code><code>* 获取主题变化,由Observer触发</code>
<code> </code><code>*/</code>
<code> </code><code>public</code> <code>void</code> <code>update();</code>
<code> </code><code>/**设置主题对象*/</code>
<code> </code><code>public</code> <code>void</code> <code>setSubject(Subject sbj);</code>
ConcreteSubject具体主题:
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<code>public</code> <code>class</code> <code>ConcreteSubject </code><code>implements</code> <code>Subject{</code>
<code> </code><code>private</code> <code>String message;</code><code>//传递的消息体</code>
<code> </code><code>private</code> <code>boolean</code> <code>changed;</code><code>//消息状态标识</code>
<code> </code><code>//存储注册的观察者集合</code>
<code> </code><code>private</code> <code>List<Observer> observers;</code>
<code> </code><code>public</code> <code>ConcreteSubject(){</code>
<code> </code><code>this</code><code>.observers=</code><code>new</code> <code>ArrayList<Observer>();</code>
<code> </code><code>}</code>
<code> </code><code>* 这里的Subject可以是主题订阅,具体关系中的老师-学生等</code>
<code> </code><code>@Override</code>
<code> </code><code>public</code> <code>void</code> <code>attach(Observer obs) { </code>
<code> </code><code>if</code><code>(obs==</code><code>null</code><code>)</code>
<code> </code><code>throw</code> <code>new</code> <code>NullPointerException(</code><code>"Null Observer"</code><code>);</code>
<code> </code><code>if</code><code>(!observers.contains(obs))</code>
<code> </code><code>observers.add(obs);</code>
<code> </code><code>public</code> <code>void</code> <code>detach(Observer obs) {</code>
<code> </code><code>observers.remove(obs);</code>
<code> </code><code>public</code> <code>void</code> <code>noticeObservers() {</code>
<code> </code><code>List<Observer> temp=</code><code>null</code><code>;</code>
<code> </code><code>/**</code>
<code> </code><code>* 防止观察者收到订阅以前由被观察者发出的消息</code>
<code> </code><code>*/</code>
<code> </code><code>synchronized</code> <code>(ConcreteSubject.</code><code>class</code><code>) {</code>
<code> </code><code>if</code><code>(!changed)</code>
<code> </code><code>return</code><code>;</code>
<code> </code><code>temp=</code><code>new</code> <code>ArrayList<>(</code><code>this</code><code>.observers);</code>
<code> </code><code>this</code><code>.changed=</code><code>false</code><code>;</code>
<code> </code><code>}</code>
<code> </code>
<code> </code><code>for</code><code>(Observer obs:temp){</code>
<code> </code><code>/**调用观察者的方法*/</code>
<code> </code><code>obs.update();</code>
<code> </code><code>public</code> <code>String getUpdate() {</code>
<code> </code><code>return</code> <code>this</code><code>.message;</code>
<code> </code><code>public</code> <code>void</code> <code>postMessage(String msg){</code>
<code> </code><code>this</code><code>.message=msg;</code>
<code> </code><code>this</code><code>.changed=</code><code>true</code><code>;</code>
<code> </code><code>//通知到观察者</code>
<code> </code><code>noticeObservers();</code>
ConcreteObserver具体观察者:
<code>public</code> <code>class</code> <code>ConcreteObserver </code><code>implements</code> <code>Observer{</code>
<code> </code><code>//此处用于标注不同的观察者</code>
<code> </code><code>private</code> <code>String name;</code>
<code> </code><code>//消息结果字段</code>
<code> </code><code>private</code> <code>String result;</code>
<code> </code><code>//设置主题</code>
<code> </code><code>private</code> <code>Subject subject;</code>
<code> </code><code>public</code> <code>ConcreteObserver(String name){</code>
<code> </code><code>this</code><code>.name=name;</code>
<code> </code><code>public</code> <code>void</code> <code>update() {</code>
<code> </code><code>/**从主题那里取得消息更新*/</code>
<code> </code><code>result=subject.getUpdate();</code>
<code> </code><code>/**处理消息*/</code>
<code> </code><code>System.out.println(name+</code><code>" get message "</code><code>+result);</code>
<code> </code><code>public</code> <code>void</code> <code>setSubject(Subject sbj) {</code>
<code> </code><code>this</code><code>.subject=sbj;</code>
发布-订阅实例:
<code>public</code> <code>class</code> <code>OBClient {</code>
<code> </code><code>public</code> <code>static</code> <code>void</code> <code>main(String[] args){</code>
<code> </code><code>ConcreteSubject sbj=</code><code>new</code> <code>ConcreteSubject();</code>
<code> </code><code>ConcreteObserver obs1=</code><code>new</code> <code>ConcreteObserver(</code><code>"obs1"</code><code>);</code>
<code> </code><code>ConcreteObserver obs2=</code><code>new</code> <code>ConcreteObserver(</code><code>"obs2"</code><code>);</code>
<code> </code><code>ConcreteObserver obs3=</code><code>new</code> <code>ConcreteObserver(</code><code>"obs3"</code><code>);</code>
<code> </code><code>/**注册到主题*/</code>
<code> </code><code>sbj.attach(obs1);</code>
<code> </code><code>sbj.attach(obs2);</code>
<code> </code><code>sbj.attach(obs3);</code>
<code> </code><code>/**设置被观察对象*/</code>
<code> </code><code>obs1.setSubject(sbj);</code>
<code> </code><code>obs2.setSubject(sbj);</code>
<code> </code><code>obs3.setSubject(sbj);</code>
<code> </code><code>/**发送消息*/</code>
<code> </code><code>sbj.postMessage(</code><code>"hello world!"</code><code>);</code>
测试结果:
<b>本文转自邴越博客园博客,原文链接:http://www.cnblogs.com/binyue/p/3728485.html,如需转载请自行联系原作者</b>