定義
觀察者模式是對象的行為模式污抬,又叫發(fā)布-訂閱(Publish/Subscribe)模式,模型-視圖-模式(Model/View)模式,源-監(jiān)聽器(Source/Listener)模式或從屬者(dependents)模式努咐。
一個軟件系統(tǒng)常常要求在某一個對象的狀態(tài)發(fā)生改變的時候某些其它的對象做出相應的改變攘轩,觀察者模式是滿足這一要求的最重要的一種方案。
根據(jù)觀察者對象的引用位置,觀察者模式分為兩種
-
一
這種實現(xiàn)在傳統(tǒng)的模式著作和討論中比較常見
-
二
java提供的觀察者模型就屬于這種
觀察者模式的結(jié)構(gòu)
第一種結(jié)構(gòu)
第一種實現(xiàn)的模式如下
- 抽象主題(Subject)角色
主題角色把所有對觀察者對象的引用保存在一個集合(比如Vector對象)里恋脚,每一個主題都可以有任意數(shù)量的觀察者。抽象主題提供一個接口焰手,可以增加和刪除觀察者對象糟描,主題角色又叫抽象被觀察者角色public interface Subject { /** * 注冊一個新的觀察者對象 * @param observer 觀察者 */ void attach(Observer observer); /** * 刪除該觀察者 * @param observer 要刪除的觀察者對象 */ void detach(Observer observer); /** * 通知全部已經(jīng)注冊過的觀察者 */ void notifyObservers(); }
- 抽象觀察者(Observer)角色
為所有具體的觀察者定義一個接口,在得到主題的通知時時更新自己书妻,這個接口叫做更新接口public interface Observer { /** * 觀察者更新方法 */ void update(); }
- 具體主題(ConcreteSubject)角色
擁有全部的觀察者對象集合船响,在具體主題的內(nèi)部狀態(tài)改變時,給所有的觀察者發(fā)送通知躲履。具體主題角色又叫具體被觀察角色public class ConcreteSubject implements Subject{ private Vector observersVector = new Vector(); 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(); } } private Enumeration observers(){ return ((Vector)observersVector.clone()).elements(); } }
- 具體觀察者(ConcreteObserver)角色
具體觀察者角色實現(xiàn)實現(xiàn)抽象觀察者所要求的更新接口public class ConcreteObserver implements Observer{ public void update() { System.out.println("I am notified"); } }
- 測試
public class MySubject extends ConcreteSubject { public void change(){ System.out.println("data change..."); notifyObservers(); } }
public class ObserverTest { Observer observerA; Observer observerB; MySubject subject; @Before public void before(){ observerA = new ConcreteObserver(); observerB = new ConcreteObserver(); subject = new MySubject(); subject.attach(observerA); subject.attach(observerB); } @Test public void testObserver(){ subject.change(); } }
第二種結(jié)構(gòu)
第二種實現(xiàn)的模式如下
第二中與第一種基本相同
- 抽象主題角色
subject類可以用抽象類或類實現(xiàn)public abstract class Subject { private Vector observersVector = new Vector(); 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(); } } private Enumeration observers(){ return ((Vector)observersVector.clone()).elements(); } }
- 具體主題角色
public class ConcreteSubject extends Subject { private String data; public void change(String newData){ data = newData; System.out.println("data change"); notifyObservers(); } }
- 抽象觀察者和具體觀察者代碼與第一種結(jié)構(gòu)完全相同
- 測試
public class ObserverTest { Observer observerA; Observer observerB; ConcreteSubject subject; @Before public void before(){ observerA = new ConcreteObserver(); observerB = new ConcreteObserver(); subject = new ConcreteSubject(); subject.attach(observerA); subject.attach(observerB); } @Test public void testObserver(){ subject.change("test"); } }