觀察者模式(Observer Pattern)也叫做釋出-訂閱(Publish/Subscribe)模式、模型-檢視(Model/View)模式。這個模式的一個最重要的作用就是解耦。也就是將被觀察者和觀察者進行解耦,使得他們之間的依賴性更小,甚至做到毫無依賴。
觀察者模式的定義:該模式定義了物件之間的一對多依賴關係,Subject 物件是一,Observer 物件是多。當 Subject 物件的狀態發生改變時,所有依賴於該 Subject 物件的 Observer 物件都會得到通知,並且自動更新。
仔細分析定義,要精確理解觀察者模式主要注意三點:
定義了物件間的一對多依賴關係。
當 Subject 物件的狀態發生改變時,所有依賴於該 Subject 物件的 Observer 物件都會得到通知。
Observer 物件得到通知後,會自動更新,而不是被動。
經過上面的分析,下面我用程式碼簡單實現上述邏輯。
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點核心思想,對比程式碼和三點思想,是不是完美一致?百度一下"觀察者模式",實現邏輯大都是複雜高深,其實就核心的思想來說,上面的示例足夠了,其它擴充套件要以具體的業務需求來決定。比如:
Subject 角色是應該定義成類?比如 內建的 java.util.Observable;還是應該定義成介面,以規避Java不支援多重繼承的問題?
應該在什麼時候訂閱主題(或者說註冊觀察者)?是例項化觀察者物件的同時?還是由客戶自主決定?
是否應該實現取消訂閱功能(或者說取消註冊)?
主題物件通知觀察者時,是否攜帶訊息?換句話說,是“推”訊息?還是“拉”訊息?
是否支援多執行緒?