設計模式學習——觀察者模式
觀察者模式
- 定義:定義物件間一種一對多的依賴關係,使得每當一個物件發生變化時,則所有依賴於他的物件都會得到通知並自動更新。
- 使用場景
- 關聯行為場景
- 事件多級觸發場景
- 跨系統的訊息交換場景,如訊息佇列、事件匯流排的處理機制
-
特點:實現物件的解耦,將觀察者和被觀察者完全隔離,只依賴於Observe和Observable抽象。
UML
-
簡單實現例子
- 抽象觀察者類
/** * 抽象觀察者類,為所有具體觀察者定義一個介面,在得到通知時更新自己 */ public interface Observer { /** * 有更新 * @param message 訊息 */ public void update(String message); }
- 抽象被觀察者
/**
* 抽象被觀察者類
*/
public interface Observable {/**
* 推送訊息
* @param message 內容
*/
void push(String message);
/**
* 訂閱方法,提供給訂閱者訂閱
* @param observer 訂閱者
*/
void register(Observer observer);
}
- 具體的觀察者類
/** * 具體的觀察者類,也就是訂閱者 */ public class User implements Observer { /**被觀察者發生變化後觀察者要做出的反應**/ @Override public void update(String message) { System.out.println(name + "," + message + "更新了!"); } // 訂閱者的名字private String name; public User(String name) { this.name = name; } }
- 具體的被觀察者類
/** * 具體的被觀察者類,也就是訂閱的節目 */ public class Teleplay implements Observable{ private List<Observer> list = new ArrayList<Observer>();//儲存訂閱者 @Override public void push(String message) { for(Observer observer:list){ observer.update(message); } } @Overridepublic void register(Observer observer) { list.add(observer); } }
- 使用
public class Client {
public static void main(String[] args) {
//被觀察者,這裡就是使用者訂閱的電視劇
Teleplay teleplay = new Teleplay();
//觀察者,這裡就是訂閱使用者
User user1 = new User("小明");
User user2 = new User("小光");
User user3 = new User("小蘭");
//訂閱
teleplay.register(user1);
teleplay.register(user2);
teleplay.register(user3);
//推送新訊息
teleplay.push("xxx電視劇");
}
}
列印結果:
小明,xxx電視劇更新了!
小光,xxx電視劇更新了!
小蘭,xxx電視劇更新了!
Observe 和Observable都是JDK中的內建型別,可見觀察者模式非常重要。達到一對多的通知功能,通知系統都是依賴Observe 和Observable的。
- 安卓中使用的觀察者模式
- ListView
首先在Android中,我們往ListView新增資料後,都會呼叫Adapter的notifyDataChanged()方法,其中使用了觀察者模式。
當ListView的資料發生變化時,呼叫Adapter的notifyDataSetChanged函式,這個函式又會呼叫DataSetObservable的notifyChanged函式,這個函式會呼叫所有觀察者( )的onChanged方法,在onChanged函式中又會呼叫ListView重新佈局的函式使得ListView重新整理介面。
- 廣播
Android中應用程式傳送廣播的過程:
通過sendBroadcast把一個廣播通過Binder傳送給ActivityManagerService,ActivityManagerService根據這個廣播的Action型別找到相應的廣播接收器,然後把這個廣播放進自己的訊息佇列中,就完成第一階段對這個廣播的非同步分發。
ActivityManagerService在訊息迴圈中處理這個廣播,並通過Binder機制把這個廣播分發給註冊的ReceiverDispatcher,ReceiverDispatcher把這個廣播放進MainActivity所線上程的訊息佇列中,就完成第二階段對這個廣播的非同步分發:
ReceiverDispatcher的內部類Args在MainActivity所在的執行緒訊息迴圈中處理這個廣播,最終是將這個廣播分發給所註冊的BroadcastReceiver例項的onReceive函式進行處理。
- 事件匯流排 ——EvenBus框架