(《設計模式解析與實戰——何紅輝,關愛民》讀書筆記)
一、定義
定義對象間同一種一對多的依賴關係,使得每當一個對象改變狀態,則所有依賴於它的對象都會得到通知並被自動更新。
比如。手機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中消息的通知默認是順序執行,一個觀察者卡頓,會影響整體的執行效率,在這種情況下,一般考慮採用異步的方式。