1. 概述
有時被稱作發佈/訂閱模式,觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己。
2. 解決的問題
將一個系統分割成一個一些類相互協作的類有一個不好的副作用,那就是需要維護相關對象間的一致性。我們不希望爲了維持一致性而使各類緊密耦合,這樣會給維護、擴展和重用都帶來不便。觀察者就是解決這類的耦合關係的。
3. 模式中的角色
3.1 抽象主題(Subject):它把所有觀察者對象的引用保存到一個聚集裏,每個主題都可以有任何數量的觀察者。抽象主題提供一個接口,可以增加和刪除觀察者對象。
3.2 具體主題(ConcreteSubject):將有關狀態存入具體觀察者對象;在具體主題內部狀態改變時,給所有登記過的觀察者發出通知。
3.3 抽象觀察者(Observer):爲所有的具體觀察者定義一個接口,在得到主題通知時更新自己。
3.4 具體觀察者(ConcreteObserver):實現抽象觀察者角色所要求的更新接口,以便使本身的狀態與主題狀態協調。
4.代碼
用代碼模擬一個消息生產者(具體主題)的消息內容發生了更新,需要向他的多個消費者(具體觀察者)發出最新的消息的場景。
/** * 作爲一個具體主題,當message發生更新時,向他所有的觀察者發佈最新的消息 * Created by yangjiachang on 2016/8/25. */ public class MessageProducer extends Observable{ private String message; public void pushMessage(String msg){ if (StringUtils.isBlank(msg)){ throw new NullPointerException(); } if (StringUtils.equals(message,msg)){ return; } message = msg; System.out.println("發佈消息"); //內部狀態發生改變 setChanged(); //向觀察者發佈最新消息 notifyObservers(); } public String getMessage() { return message; } }
/** * 作爲具體觀察者,接受主題發送過來的消息,並完成自身業務邏輯 * Created by yangjiachang on 2016/8/25. */ public class MessageConsumer implements Observer { public void update(Observable o, Object arg) { if(o instanceof MessageProducer){ MessageProducer messageProducer = (MessageProducer)o; //獲取消息 String message = messageProducer.getMessage(); //處理業務邏輯 view(message); } } private void view(String message){ System.out.println("閱讀消息:"+message); }
public class Test { public static void main(String[] args){ MessageProducer producer = new MessageProducer(); producer.addObserver(new MessageConsumer()); producer.addObserver(new MessageConsumer()); producer.addObserver(new MessageConsumer()); System.out.println("當前共有" + producer.countObservers() + "個觀察者"); producer.pushMessage("您有一條新消息:aaa"); producer.pushMessage("您有一條新消息:bbb"); } }運行結果:
當前共有3個觀察者
發佈消息
閱讀消息:您有一條新消息:aaa
閱讀消息:您有一條新消息:aaa
閱讀消息:您有一條新消息:aaa
發佈消息
閱讀消息:您有一條新消息:bbb
閱讀消息:您有一條新消息:bbb
閱讀消息:您有一條新消息:bbb
通過以上的例子定義了一個消息生產者(主題),以及它的消費者(觀察者),先後發出了2條消息,均被消費者接收並完成閱讀。
這個例子中的具體主題就是MessageProducer類,他繼承了抽象主題Observable類;具體觀察者MessageConsumer類實現了抽象觀察者Observer接口。
下面我們通過源碼瞭解一下抽象主題Observable類,和抽象觀察者Observer接口。
Observable類中有2個變量,分別是:
private boolean changed = false; private Vector<Observer> obs;其中changed表示主題的內部是否發生了變化,通過setChanged()方法將changed賦值爲true,clearChanged()方法賦值爲false,hasChanged()方法查詢當前狀態;
obs記錄了該主題的觀察者有哪些,通過addObserver(Observer o)方法添加觀察者,deleteObserver(Observer o)方法刪除觀察者,countObserver()方法獲取當前觀察者數量。
通過notifyObserver方法向觀察者發佈主題內容。
具體觀察者只需要實現Observer接口中的update方法完成自身業務邏輯。