Android 設計模式 - 觀察者模式
最近在看「Head First 設計模式」,感覺收穫很大,對架構設計有了更深的理解。我會陸續記錄讀後的心得,並進行編碼實踐,強化理解。
觀察者模式是常用的設計模式之一,它的定義是這樣的:
觀察者模式定義了一個一對多的依賴關係,讓一個或多個觀察者物件監聽一個主題物件。這樣一來,當被觀察者狀態發生改變時,需要通知相應的觀察者,使這些觀察者物件能夠自動更新。
關鍵的兩個角色:觀察者和被觀察者。
觀察者(observer)
當被觀察者發生變化時,觀察者會收到通知,並進行相應的處理。
被觀察者(observable)
內部持有觀察者的集合,在觀察者註冊和解除註冊時用。當資料發生變化時,及時通知觀察者。
實戰演練:我拿微信使用者訂閱公眾號的例子進行說明。

類圖
觀察者介面:微信使用者,能夠接收訊息。
public interface IWechatUser { /** * 接收到訊息 * * @param message */ void onReceived(String message); }
被觀察者介面:微信公眾號,主要有三個方法:訂閱、取消和群發。
public interface IOfficialAccount { /** * 訂閱公眾號 * * @param wechatUser */ void addSubscriber(IWechatUser wechatUser); /** * 取消訂閱公眾號 * * @param wechatUser */ void removeSubscriber(IWechatUser wechatUser); /** * 群發訊息 * * @param message */ void notifySubscribers(String message); }
微信使用者實現類,構造時就讓他關注公眾號,在收到訊息時進行顯示。
public class WechatUser implements IWechatUser { private String name; public WechatUser(String name, IOfficialAccount officialAccount) { this.name = name; officialAccount.addSubscriber(this); } @Override public void onReceived(String message) { System.out.println(this.name + " 收到: " + message); } }
公眾號實現類,提供關注和取關的介面,使用列表儲存訂閱的使用者,支援群發訊息。
public class OfficialAccount implements IOfficialAccount { private String name; private List<IWechatUser> wechatUsers; public OfficialAccount(String name) { this.name = name; wechatUsers = new ArrayList<>(); } @Override public void addSubscriber(IWechatUser wechatUser) { if (!wechatUsers.contains(wechatUser)) { wechatUsers.add(wechatUser); } } @Override public void removeSubscriber(IWechatUser wechatUser) { wechatUsers.remove(wechatUser); } @Override public void notifySubscribers(String message) { for (IWechatUser wechatUser : wechatUsers) { wechatUser.onReceived(name + " - " + message); } } }
測試:
IOfficialAccount xdxx = new OfficialAccount("小道訊息"); IOfficialAccount rmrb = new OfficialAccount("人民日報"); IWechatUser zs = new WechatUser("張三", xdxx); IWechatUser ls = new WechatUser("李四", rmrb); xdxx.notifyUsers("走在前沿,擁抱變化"); rmrb.notifyUsers("熱愛祖國,熱愛人民");
這樣,一個觀察者模式就實現了。下面說一下它的優點:鬆耦合。
-
被觀察者無須瞭解觀察者的細節,只負責通知觀察者。比如:公眾號作者只負責推送訊息,至於使用者看沒看,那他就不得而知了。
-
觀察者訂閱還是取消訂閱,只要呼叫新增和移除的介面即可。比如:使用者點選關注、取關按鈕就可以完成。
-
觀察者被動接收通知,不需要在意被觀察者的細節。比如:使用者等待作者推送,不必關心內容是如何排版的。
目前,觀察者模式使用推送的方式進行通知,如果觀察者只需要其中的部分資料呢?推送大量資料未免是多餘的。這時,可以採用觀察者主動向被觀察者獲取資料的方式,只取自己需要的資料。介面引數加上被觀察者的引用,這麼改動:
/** * 允許使用者主動獲取訊息 * * @param officialAccount */ void onReceivedCustom(IOfficialAccount officialAccount);
在使用的時候,直接獲取即可。
@Override public void onReceivedCustom(IOfficialAccount officialAccount) { if(officialAccount instanceof OfficialAccount){ System.out.println(this.name + " 取到: " + ((OfficialAccount) officialAccount).getCustomMessage()); } }
JDK 中存在觀察者和被觀察者的類,在 java.util 包下,Observer 介面和 Observable 類,系統給封裝好了,使用起來比較方便。
Android 裡面的事件監聽,就大量使用觀察者模式,其實主要是從鬆耦合的考慮吧。
【附錄】

資料圖
需要資料的朋友可以加入Android架構交流QQ群聊:513088520
點選連結加入群聊【Android移動架構總群】: 加入群聊
獲取免費學習視訊,學習大綱另外還有像高階UI、效能優化、架構師課程、NDK、混合式開發(ReactNative+Weex)等Android高階開發資料免費分享。