觀察者模式——解耦的鑰匙

(《設計模式解析與實戰——何紅輝,關愛民》讀書筆記)

一、定義
定義對象間同一種一對多的依賴關係,使得每當一個對象改變狀態,則所有依賴於它的對象都會得到通知並被自動更新。
比如。手機UI具有易變性,但業務邏輯基本變化不大,所以UI層需要與具體的業務邏輯解耦。

二、使用場景
(1) 關聯行爲場景,關聯行爲是可拆分的,而不是組合關係;
(2) 事件多級觸發場景;
(3) 跨系統的消息交換場景,如消息隊列、事件總線的處理機制。

三、簡單實現

/**
 * 觀察者:人
 */
public class ManObserver implements Observer {

    public String name;

    public ManObserver(String name) {
        super();
        this.name = name;
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.println("你好," + name + ",**網站地址變化啦,新地址:" + arg);
    }

    @Override
    public String toString() {
        return "ManObserver [name=" + name + "]";
    }
}
/**
 * 被觀察者:XX網站
 */
public class XXWebsite extends Observable{
    public void postNewWebURL(String webURL) {
        // 標識狀態或者內容發生改變
        setChanged();
        // 通知所有觀察者
        notifyObservers(webURL);
    }
}
/**
 * 測試
 */
public class Test {
    public static void main(String[] args) {
        // 被觀察者的角色
        XXWebsite xxWebsite = new XXWebsite();

        // 觀察者
        ManObserver observer1 = new ManObserver("Man1");
        ManObserver observer2 = new ManObserver("Man2");
        ManObserver observer3 = new ManObserver("Man3");

        // 將觀察者註冊到可觀察對象的觀察者列表中
        xxWebsite.addObserver(observer1);
        xxWebsite.addObserver(observer2);
        xxWebsite.addObserver(observer3);

        // 發佈消息
        xxWebsite.postNewWebURL("www.******.com");
    }
}

運行結果:
這裏寫圖片描述
Observer:抽象觀察者,定義了一個更新接口,使得在得到主題的更改通知時更新自己;
ManObserver:(ConcreteObserver)具體的觀察者,該角色實現抽象觀察者灰色所定義的更新接口,以便在主題的狀態發生變化時更新自身的狀態;
Observable:抽象被觀察者,該角色把所有觀察者對象的引用保存在一個集合裏,每個被觀察者都可以有任意數量的觀察者,被觀察者提供一個接口,可以增加和刪除觀察者對象xxWebsite.deleteObserver(observer1);
XXWebsite:具體的被觀察者對象,該角色將有關狀態存入具體觀察者對象,在具體被觀察者對象的內部狀態發生改變時,給所有註冊過的觀察者發出通知。

四、總結
觀察者模式主要的作用就是對象解耦,將觀察者與被觀察者完全隔離,只依賴於Observer與Observable抽象。例如,ListView就是運用了Adapter和觀察者模式使得它的可擴展性、靈活性非常高,而耦合度卻很低。
優點:
(1) 觀察者和被觀察者之間是抽象耦合,應對業務變化;
(2) 增強系統靈活性、可擴展性。
缺點:
需要考慮開發效率和運行效率的問題。Java中消息的通知默認是順序執行,一個觀察者卡頓,會影響整體的執行效率,在這種情況下,一般考慮採用異步的方式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章