JAVA設計模式—觀察者模式(Observer)__JAVA

來源:互聯網
上載者:User

定義:定義對象間一種一對多的依賴關係,使得當每一個對象改變狀態,則所有依賴於它的對象都會得到通知並自動更新。

類型:對象行為型模式

別名:發布—訂閱(Publish - Subscribe)

類圖:

        在軟體系統中經常會有這樣的需求:如果一個對象的狀態發生改變,某些與它相關的對象也要隨之做出相應的變化。比如,我們要設計一個右鍵菜單的功能,只要在軟體的有效地區內點擊滑鼠右鍵,就會彈出一個菜單;再比如,我們要設計一個自動部署的功能,就像eclipse開發時,只要修改了檔案,eclipse就會自動將修改的檔案部署到伺服器中。這兩個功能有一個相似的地方,那就是一個對象要時刻監聽著另一個對象,只要它的狀態一發生改變,自己隨之要做出相應的行動。其實,能夠實現這一點的方案很多,但是,無疑使用觀察者模式是一個主流的選擇。

Observer模式描述了如何建立這種關係。這一模式中的關鍵對象是目標(subject)和觀察者(observer)。一個目標可以有任意數目的依賴於它的觀察者。一旦目標的狀態發生改變,所有的觀察者都得到通知。作為對這個通知的響應,每個觀察者都查詢目標以使其狀態與目標狀態同步。

這種互動也稱為 發布 - 訂閱(Publish - Subscribe)。目標是通知的發行者。它發出通知時並不需要知道誰是它的觀察者。可以有任意數目的觀察者訂閱並接受通知。


觀察者模式的結構

在最基礎的觀察者模式中,包括以下四個角色: 被觀察者:從類圖中可以看到,類中有一個用來存放觀察者對象的Vector容器(之所以使用Vector而不使用List,是因為多線程操作時,Vector在是安全的,而List則是不安全的),這個Vector容器是被觀察者類的核心,另外還有三個方法:attach方法是向這個容器中添加觀察者對象;detach方法是從容器中移除觀察者對象;notify方法是依次調用觀察者對象的對應方法。這個角色可以是介面,也可以是抽象類別或者具體的類,因為很多情況下會與其他的模式混用,所以使用抽象類別的情況比較多。 觀察者:觀察者角色一般是一個介面,它只有一個update方法,在被觀察者狀態發生變化時,這個方法就會被觸發調用。 具體的被觀察者:使用這個角色是為了便於擴充,可以在此角色中定義具體的商務邏輯。 具體的觀察者:觀察者介面的具體實現,在這個角色中,將定義被觀察者對象狀態發生變化時所要處理的邏輯。

觀察者模式代碼實現

//抽象目標abstract class Subject {private Vector<Observer> obs = new Vector<Observer>();//觀察者列表需要同步public synchronized  void registerObserver(Observer obs) {this.obs.add(obs);}public synchronized  void unRegisterObserver(Observer obs) {this.obs.remove(obs);}//發送通知訊息protected void notifyObserver() {for (Observer o : obs) {o.update();}}public abstract void doSomething();}//具體目標class ConcreteSubject extends Subject {public void doSomething() {System.out.println("被觀察者事件發生");this.notifyObserver();}}//觀察者介面interface Observer {public void update();}//具體觀察者,實現update操作class ConcreteObserver1 implements Observer {public void update() {System.out.println("觀察者1收到資訊,並進行處理。");}}class ConcreteObserver2 implements Observer {public void update() {System.out.println("觀察者2收到資訊,並進行處理。");}}public class ObserverClient {/** * @param args */public static void main(String[] args) {Subject sub = new ConcreteSubject();sub.registerObserver(new ConcreteObserver1()); // 添加觀察者1sub.registerObserver(new ConcreteObserver2()); // 添加觀察者2sub.doSomething();}}


運行結果

被觀察者事件發生

觀察者1收到資訊,並進行處理。

觀察者2收到資訊,並進行處理。

        通過運行結果可以看到,我們只調用了Subject的方法,但同時兩個觀察者的相關方法都被同時調用了。仔細看一下代碼,其實很簡單,無非就是在Subject類中關聯一下Observer類,並且在doSomething方法中遍曆一下Observer的update方法就行了。


觀察者模式的優缺點

目標和觀察者的之間的抽象耦合 一個目標所知道的僅僅是它有一系列觀察者,每個都符合抽象的Observer類的簡單介面。目標不知道任何一個觀察者屬於哪一個具體的類。這樣目標和觀察者之間的耦合是抽象的和最小的。因為目標和觀察者不是緊密耦合的,它們可以屬於一個系統中的不同抽象層次。一個處於較低層次的目標對象可與一個處於較高層次的觀察者通訊並通知它,這樣就保持了系統層次的完整。 支援廣播通訊 不像通常的請求,目標發送的通知不需要指定它的接收者。通知被自動廣播給所有已向該目標對象登記的有關對象。目標對象並不關心到底有多少對象對自己感興趣;它唯一的責任就是通知它的各觀察者。這給了你在任何時刻增加和刪除觀察者的自由。處理還是忽略一個通知取決於 觀察者。 意外的更新 因為一個觀察者並不知道其他觀察者的存在,它可能對改變目標的最終代價一無所知。在目標上一個看似無害的操作可能會引起一系列對觀察者以及依賴於觀察者的那些對象的更新。此外,如果依賴準則的定義或維護不當,常常會引起錯誤的更新,這種錯誤通常很難捕捉。

適用性

在以下任一情況可以使用觀察者模式:

當一個抽象模型有兩個方面,其中一個方面依賴於另一個方面。將這二者封裝在獨立的對象中以使它們可以各自獨立的改變和複用。 當一個對象的改變需要同時改變其他對象,而不知道具體有多少對象有待改變。 當一個對象必須通知其他對象,而它又不能假定其他對象是誰。換言之,你不希望這些對象是緊密耦合的。


總結

       java語言中,有一個介面Observer,以及它的實作類別Observable,對觀察者角色常進行了實現。我們可以在jdk的api文檔具體查看這兩個類的使用方法。

       做過VC++、javascript DOM或者AWT開發的朋友都對它們的事件處理感到神奇,瞭解了觀察者模式,就對事件處理機制的原理有了一定的瞭解了。如果要設計一個事件觸發處理機制的功能,使用觀察者模式是一個不錯的選擇,AWT中的事件處理DEM(委派事件模型Delegation Event Model)就是使用觀察者模式實現的。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.