爪哇語言觀察者模式介紹
簡單地說,觀察者模式定義了一個一對多的依賴關系,讓一個或多個觀察者對象監察一個主題對象。這樣一個主題對象在狀態上的變化能夠通知所有的依賴于此對象的那些觀察者對象,使這些觀察者對象能夠自動更新。
觀察者模式的結構
觀察者(Observer)模式是對象的行為型模式,又叫做發表-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-收聽者(Source/Listener)模式或從屬者(Dependents)模式。
本模式的類圖結構如下:
![]() 圖1、觀察者模式的靜態結構可從類圖中看清楚。 |
在觀察者模式里有如下的角色:
. 抽象主題(Subject)角色:主題角色把所有的觀察者對象的引用保存在一個列表里;每個主題都可以有任何數量的觀察者。主題提供一個接口可以加上或撤銷觀察者對象;主題角色又叫做抽象被觀察者(Observable)角色;
![]() 圖2、抽象主題角色,有時又叫做抽象被觀察者角色,可以用一個抽象類或者一個接口實現;在具體的情況下也不排除使用具體類實現。 |
. 抽象觀察者(Observer)角色:為所有的具體觀察者定義一個接口,在得到通知時更新自己;
![]() 圖3、抽象觀察者角色,可以用一個抽象類或者一個接口實現;在具體的情況下也不排除使用具體類實現。 |
. 具體主題(ConcreteSubject)角色:保存對具體觀察者對象有用的內部狀態;在這種內部狀態改變時給其觀察者發出一個通知;具體主題角色又叫作具體被觀察者角色;
![]() 圖4、具體主題角色,通常用一個具體子類實現。 |
.具體觀察者(ConcreteObserver)角色:保存一個指向具體主題對象的引用;和一個與主題的狀態相符的狀態。具體觀察者角色實現抽象觀察者角色所要求的更新自己的接口,以便使本身的狀態與主題的狀態自恰。
![]() 圖5、具體觀察者角色,通常用一個具體子類實現。 |
下面給出一個示意性實現的Java代碼。首先在這個示意性的實現里,用一個Java接口實現抽象主題角色,這就是下面的Subject接口:
public interface Subject { public void attach(Observer observer); public void detach(Observer observer); void notifyObservers(); } |
這個抽象主題接口規定出三個子類必須實現的操作,即 attach() 用來增加一個觀察者對象;detach() 用來刪除一個觀察者對象;和notifyObservers() 用來通知各個觀察者刷新它們自己。抽象主題角色實際上要求子類保持一個以所有的觀察者對象為元素的列表。
具體主題則是實現了抽象主題Subject接口的一個具體類,它給出了以上的三個操作的具體實現。從下面的源代碼可以看出,這里給出的Java實現使用了一個Java向量來保存所有的觀察者對象,而 attach() 和 detach() 操作則是對此向量的元素增減操作。
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(); } |
抽象觀察者角色的實現實際上是最為簡單的一個,它是一個Java接口,只聲明了一個方法,即update()。這個方法被子類實現后,一被調用便刷新自己。
public interface Observer { void update(); } |
具體觀察者角色的實現其實只涉及update()方法的實現。這個方法怎么實現與應用密切相關,因此本類只給出一個框架。
public class ConcreteObserver implements Observer { public void update() { // Write your code here } } |
雖然觀察者模式的實現方法可以有設計師自己確定,但是因為從AWT1.1開始視窗系統的事件模型采用觀察者模式,因此觀察者模式在Java語言里的地位較為重要。正因為這個原因,Java語言給出了它自己對觀察者模式的支持。因此,本文建議讀者在自己的系統中應用觀察者模式時,不妨利用Java語言所提供的支持。