深刻理解[觀察者模式]原理與技術

觀察者模式(Observer Pattern)也叫作發佈-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式。這個模式的一個最重要的做用就是解耦。也就是將被觀察者和觀察者進行解耦,使得他們之間的依賴性更小,甚至作到毫無依賴。java

觀察者模式的定義:該模式定義了對象之間的一對多依賴關係,Subject 對象是一,Observer 對象是多。當 Subject 對象的狀態發生改變時,全部依賴於該 Subject 對象的 Observer 對象都會獲得通知,而且自動更新。多線程

仔細分析定義,要精確理解觀察者模式主要注意三點:ide

  1. 定義了對象間的一對多依賴關係。this

  2. 當 Subject 對象的狀態發生改變時,全部依賴於該 Subject 對象的 Observer 對象都會獲得通知。線程

  3. Observer 對象獲得通知後,會自動更新,而不是被動。code

通過上面的分析,下面我用代碼簡單實現上述邏輯。server

1.首先須要定義一個觀察者對象,內部含有data數據(getter、setter、構造方法、toString)。對象

public class Observer {
    private String data;

    public Observer(String data) {
        this.data = data;
    }

    public String getData() {
        return data;
    }

    public void setData(String data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "Observer{" +
                "data='" + data + '\'' +
                '}';
    }
}

2.其次定義主題對象,主題對象內部提供觀察者綁定(register)的接口,而且能夠更新(update)所綁定的觀察者對象。繼承

public class Subject {
    private List<Observer> list = new ArrayList<>();

    public void register(Observer observer){
        list.add(observer);
    }

    public void update(){
        list.forEach(observer -> {
            observer.setData("new");
            System.out.println(observer.toString());
        });
    }

}

3.最後就是main方法。接口

public static void main(String[] args) {
        Subject subject = new Subject();
        for (int i = 0; i < 3; i++) {
            Observer observer = new Observer("old");
            subject.register(observer);
            System.out.println(observer.toString());
        }
        System.out.println("update...");
        subject.update();
    }

控制檯打印

Observer{data='old'}
Observer{data='old'}
Observer{data='old'}
update...
Observer{data='new'}
Observer{data='new'}
Observer{data='new'}

看到這裏你也許會問:這就是觀察者模式?這麼簡單?你莫不是在逗我?

是的,這就是觀察者模式。咱們從觀察者模式的定義出發,抽取出關鍵的3點核心思想,對比代碼和三點思想,是否是完美一致?百度一下"觀察者模式",實現邏輯大都是複雜高深,其實就核心的思想來講,上面的示例足夠了,其它擴展要以具體的業務需求來決定。好比:

  1. Subject 角色是應該定義成類?好比 內置的 java.util.Observable;仍是應該定義成接口,以規避Java不支持多重繼承的問題?

  2. 應該在何時訂閱主題(或者說註冊觀察者)?是實例化觀察者對象的同時?仍是由客戶自主決定?

  3. 是否應該實現取消訂閱功能(或者說取消註冊)?

  4. 主題對象通知觀察者時,是否攜帶消息?換句話說,是「推」消息?仍是「拉」消息?

  5. 是否支持多線程?

相關文章
相關標籤/搜索