觀察者模式(又被稱為釋出-訂閱模式、模型-視圖模式、源-收聽者模式或從屬者模式)
觀察者模式中,一個目标對象管理所有依賴于它的觀察者對象,并且在它本身的狀态改變時主動發出通知。
應用場景
拍賣會可以認為是觀察者模式的一種,每個投标人都可以出價。拍賣師開始拍賣時,他觀察是否有牌子舉起出價。每次接受一個新的出價都改變了拍賣的目前價格,并且廣播給所有的投标人。
在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>