![]() 圖1、觀察者模式的靜態(tài)結(jié)構(gòu)可從類(lèi)圖中看清楚。 |
在觀察者模式里有如下的角色:
. 抽象主題(Subject)角色:主題角色把所有的觀察者對(duì)象的引用保存在一個(gè)列表里;每個(gè)主題都可以有任何數(shù)量的觀察者。主題提供一個(gè)接口可以加上或撤銷(xiāo)觀察者對(duì)象;主題角色又叫做抽象被觀察者(Observable)角色;
![]() 圖2、抽象主題角色,有時(shí)又叫做抽象被觀察者角色,可以用一個(gè)抽象類(lèi)或者一個(gè)接口實(shí)現(xiàn);在具體的情況下也不排除使用具體類(lèi)實(shí)現(xiàn)。 |
. 抽象觀察者(Observer)角色:為所有的具體觀察者定義一個(gè)接口,在得到通知時(shí)更新自己;
![]() 圖3、抽象觀察者角色,可以用一個(gè)抽象類(lèi)或者一個(gè)接口實(shí)現(xiàn);在具體的情況下也不排除使用具體類(lèi)實(shí)現(xiàn)。 |
. 具體主題(ConcreteSubject)角色:保存對(duì)具體觀察者對(duì)象有用的內(nèi)部狀態(tài);在這種內(nèi)部狀態(tài)改變時(shí)給其觀察者發(fā)出一個(gè)通知;具體主題角色又叫作具體被觀察者角色;
![]() 圖4、具體主題角色,通常用一個(gè)具體子類(lèi)實(shí)現(xiàn)。 |
.具體觀察者(ConcreteObserver)角色:保存一個(gè)指向具體主題對(duì)象的引用;和一個(gè)與主題的狀態(tài)相符的狀態(tài)。具體觀察者角色實(shí)現(xiàn)抽象觀察者角色所要求的更新自己的接口,以便使本身的狀態(tài)與主題的狀態(tài)自恰。
![]() 圖5、具體觀察者角色,通常用一個(gè)具體子類(lèi)實(shí)現(xiàn)。 |
下面給出一個(gè)示意性實(shí)現(xiàn)的Java代碼。首先在這個(gè)示意性的實(shí)現(xiàn)里,用一個(gè)Java接口實(shí)現(xiàn)抽象主題角色,這就是下面的Subject接口:
public interface Subject { public void attach(Observer observer); public void detach(Observer observer); void notifyObservers(); } |
import java.util.Vector; import java.util.Enumeration; public class ConcreteSubject implements Subject { public void attach(Observer observer) { observersVector.addElement(observer); } public void detach(Observer observer) { observersVector.removeElement(observer); } public void notifyObservers() { Enumeration enumeration = observers(); while (enumeration.hasMoreElements()) { ((Observer)enumeration.nextElement()).update(); } } public Enumeration observers() { return ((Vector) observersVector.clone()).elements(); } private Vector observersVector = new java.util.Vector(); } |
public interface Observer { void update(); } |
public class ConcreteObserver implements Observer { public void update() { // Write your code here } } |
![]() 圖6、java.util提供的Observer接口的類(lèi)圖。 |
package java.util; public interface Observer { /** * 當(dāng)被觀察的對(duì)象發(fā)生變化時(shí),這個(gè)方法會(huì)被調(diào)用。 */ void update(Observable o, Object arg); } |
![]() 圖7、Java語(yǔ)言提供的被觀察者的類(lèi)圖。 |
package java.util; public class Observable { private boolean changed = false; private Vector obs; /** 用0個(gè)觀察者構(gòu)造一個(gè)被觀察者。**/ public Observable() { obs = new Vector(); } /** * 將一個(gè)觀察者加到觀察者列表上面。 */ public synchronized void addObserver(Observer o) { if (!obs.contains(o)) { obs.addElement(o); } } /** * 將一個(gè)觀察者對(duì)象從觀察者列表上刪除。 */ public synchronized void deleteObserver(Observer o) { obs.removeElement(o); } /** * 相當(dāng)于 notifyObservers(null) */ public void notifyObservers() { notifyObservers(null); } /** * 如果本對(duì)象有變化(那時(shí)hasChanged 方法會(huì)返回true) * 調(diào)用本方法通知所有登記在案的觀察者,即調(diào)用它們的update()方法, * 傳入this和arg作為參量。 */ public void notifyObservers(Object arg) { /** * 臨時(shí)存放當(dāng)前的觀察者的狀態(tài)。參見(jiàn)備忘錄模式。 */ Object[] arrLocal; synchronized (this) { if (!changed) return; arrLocal = obs.toArray(); clearChanged(); } for (int i = arrLocal.length-1; i>=0; i--) ((Observer)arrLocal[i]).update(this, arg); } /** * 將觀察者列表清空 */ public synchronized void deleteObservers() { obs.removeAllElements(); } /** * 將“已變化”設(shè)為true */ protected synchronized void setChanged() { changed = true; } /** * 將“已變化”重置為false */ protected synchronized void clearChanged() { changed = false; } /** * 探測(cè)本對(duì)象是否已變化 */ public synchronized boolean hasChanged() { return changed; } /** * 返還被觀察對(duì)象(即此對(duì)象)的觀察者總數(shù)。 */ public synchronized int countObservers() { return obs.size(); } } |
![]() 圖8、使用Java語(yǔ)言提供的對(duì)觀察者模式的支持。 |
![]() 圖9、一個(gè)使用Observer接口和Observable類(lèi)的例子。 |
package com.javapatterns.observer.watching; import java.util.Observer; public class Tester { static private Watched watched; static private Observer watcher; public static void main(String[] args) { watched = new Watched(); watcher = new Watcher(watched); watched.changeData("In C, we create bugs."); watched.changeData("In Java, we inherit bugs."); watched.changeData("In Java, we inherit bugs."); watched.changeData("In Visual Basic, we visualize bugs."); } } |
package com.javapatterns.observer.watching; import java.util.Observable; public class Watched extends Observable { private String data = ""; public String retrieveData() { return data; } public void changeData(String data) { if ( !this.data.equals( data) ) { this.data = data; setChanged(); } notifyObservers(); } } |
package com.javapatterns.observer.watching; import java.util.Observable; import java.util.Observer; public class Watcher implements Observer { public Watcher(Watched w) { w.addObserver(this); } public void update( Observable ob, Object arg) { System.out.println("Data has been changed to: ‘" + ((Watched)ob).retrieveData() + "‘"); } } |
watched.changeData("In C, we create bugs."); watched.changeData("In Java, we inherit bugs."); watched.changeData("In Java, we inherit bugs."); watched.changeData("In Visual Basic, we visualize bugs."); |
Data has been changed to: ‘In C, we create bugs.‘ Data has been changed to: ‘In Java, we inherit bugs.‘ Data has been changed to: ‘In Visual Basic, we visualize bugs.‘ |
![]() 圖10、菩薩和菩薩的守瓶烏龜。 |
![]() 圖11、系統(tǒng)的類(lèi)圖。 |
聯(lián)系客服