像activeMQ等消息隊列中,我們經常會使用發佈訂閱模式,但是你有沒有想過,客戶端時如何及時得到訂閱的主題的信息?其實就裡就用到了觀察者模式。在軟體系統中,當一個對象的行為依賴於另一個對象的狀態時,觀察者模式就相當有用。如果不使用觀察者模式提供的通用結構,而需要我們實現類似的功能,想想我們該如何實 ...
像activeMQ等消息隊列中,我們經常會使用發佈訂閱模式,但是你有沒有想過,客戶端時如何及時得到訂閱的主題的信息?其實就裡就用到了觀察者模式。在軟體系統中,當一個對象的行為依賴於另一個對象的狀態時,觀察者模式就相當有用。如果不使用觀察者模式提供的通用結構,而需要我們實現類似的功能,想想我們該如何實現,我們只能在另外一個線程不斷監聽對象所依賴的狀態。當然下麵的例子都是基於一個進程內觀察者模式的舉例,你可能會和我當初一樣不解,消息隊列中的消費者是通過socket進行通信得到訂閱的主題的信息。其實還是一回事的,被觀察者(主題)裡面會維護一個與它有訂閱的所有消費者的連接,當被觀察者(主題)裡面添加一個消息時,就會調用自身的方法,把該消息通過維持的socket發送給所有訂閱的消費者。 下次再跳槽,我就不是僅僅調侃我掌握kafka等消息隊列的特性了,我又可以結合設計模式來侃我對消息隊列的理解,這個逼吹的響亮吧。 觀察者模式可以用於事件監聽,通知發佈等場合。可以確保觀察者在不使用輪詢監控的情況下,及時收到相關的消息和事件。
原文和作者一起討論:http://www.cnblogs.com/intsmaze/p/6017508.html
新浪微博:intsmaze劉洋洋哥
模式動機 建立一種對象與對象之間的依賴關係,一個對象發生改變時將自動通知其他對象,其他對象將相應做出反應。在此,發生改變的對象稱為觀察目標,而被通知的對象稱為觀察者,一個觀察目標可以對應多個觀察者,而且這些觀察者之間沒有相互聯繫,可以根據需要增加和刪除觀察者,使得系統更易於擴展,這就是觀察者模式的模式動機。 模式定義 觀察者模式(Observer Pattern):定義對象間的一種一對多依賴關係,使得每當一個對象狀態發生改變時,其相關依賴對象皆得到通知並被自動更新。觀察者模式又叫做發佈-訂閱(Publish/Subscribe)模式。觀察者模式是一種對象行為型模式。 模式分析 觀察者模式描述瞭如何建立對象與對象之間的依賴關係,如何構造滿足這種需求的系統。這一模式中的關鍵對象是觀察目標和觀察者,一個目標可以有任意數目的與之相依賴的觀察者,一旦目標的狀態發生改變,所有的觀察者都將得到通知。作為對這個通知的響應,每個觀察者都將即時更新自己的狀態,以與目標狀態同步,這種交互也稱為發佈-訂閱(publish-subscribe)。目標是通知的發佈者,它發出通知時並不需要知道誰是它的觀察者,可以有任意數目的觀察者訂閱它並接收通知。 觀察者模式順序圖如下所示: 模式應用 (1) JDK1.1版本及以後的各個版本中,事件處理模型採用基於觀察者模式的委派事件模型(Delegation Event Model, DEM)。 在DEM中,事件的發佈者稱為事件源(Event Source),而訂閱者叫做事件監聽器(Event Listener),在這個過程中還可以通過事件對象(Event Object)來傳遞與事件相關的信息,可以在事件監聽者的實現類中實現事件處理,因此事件監聽對象又可以稱為事件處理對象。 事件源對象、事件監聽對象(事件處理對象)和事件對象構成了Java事件處理模型的三要素。 (2) 除了AWT中的事件處理之外,Java語言解析XML的技術SAX2以及Servlet技術的事件處理機制都基於DEM,它們都是觀察者模式的應用。 (3) 觀察者模式在軟體開發中應用非常廣泛,如某電子商務網站可以在執行發送操作後給用戶多個發送商品打折信息,某團隊戰鬥游戲中某隊友犧牲將給所有成員提示等等,凡是涉及到一對一或者一對多的對象交互場景都可以使用觀察者模式。 Java語言提供的對觀察者模式的支持在java.util.Observable類中,已經實現了主要的功能,如增加觀察者,刪除觀察者和通知觀察者,我們可以直接通過繼承Observable使用這些功能。 java.util.Observer介面是觀察者介面,它的update方法會在java.util.Observable中的notifyObservers方法中被回調,以獲得最新的狀態變化。通常在觀察者模式中,Observer介面就是我們程式的核型擴展對象,具體業務邏輯會被封裝在update方法中。
public class Observable { private boolean changed = false; private Vector obs; //創建被觀察者時就創建一個它持有的觀察者列表,註意,這個列表是需要同步的。 public Observable() { obs = new Vector(); } /** * 添加觀察者到觀察者列表中去 */ public synchronized void addObserver(Observer o) { if (o == null) throw new NullPointerException(); if (!obs.contains(o)) { obs.addElement(o); } } /** * 刪除一個觀察者 */ public synchronized void deleteObserver(Observer o) { obs.removeElement(o); } /** * 這個方法接受一個參數,這個參數一直傳到觀察者里,以供觀察者使用 */ public void notifyObservers(Object arg) { 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 interface Observer { void update(Observable o, Object arg); } public class JMSObserver implements Observer{ public void update(Observable o, Object arg) { System.out.println("發送消息給jms伺服器的觀察者已經被執行"); } } public class Subject extends Observable{ /** * 業務方法,一旦執行某個操作,則通知觀察者,在隊列模式中,其實就是當消息被添加到隊列的時候,添加進隊方法裡面調用了通知方法。 */ public void doBusiness(){ if (true) { super.setChanged(); } notifyObservers("現在還沒有的參數"); } public static void main(String [] args) { //創建一個被觀察者 Subject subject = new Subject(); //創建觀察者 Observer jmsObserver = new JMSObserver(); //把兩個觀察者加到被觀察者列表中 subject.addObserver(jmsObserver); //執行業務操作 subject.doBusiness(); } }MVC模式(有空,研究代碼好好理解,有時加分調侃項目) MVC模式是一種架構模式,它包含三個角色:模型(Model),視圖(View)和控制器(Controller)。觀察者模式可以用來實現MVC模式,觀察者模式中的觀察目標就是MVC模式中的模型(Model),而觀察者就是MVC中的視圖(View),控制器(Controller)充當兩者之間的中介者(Mediator)。當模型層的數據發生改變時,視圖層將自動改變其顯示內容。