裝載請標明出處:https://www.cnblogs.com/tangZH/p/11175120.html 觀察者模式 說白了,就是一個對發生改變,所有依賴於它的對象也發生改變,這是一對多的關係。 比如對象A,對象B,對象C。B與C依賴於A,那麼A發生改變,B與C也將發生改變。此時A是被觀察者,B ...
裝載請標明出處:https://www.cnblogs.com/tangZH/p/11175120.html
觀察者模式
說白了,就是一個對發生改變,所有依賴於它的對象也發生改變,這是一對多的關係。
比如對象A,對象B,對象C。B與C依賴於A,那麼A發生改變,B與C也將發生改變。此時A是被觀察者,B與C是觀察者。
觀察者模式又被稱作發佈/訂閱模式,主要是為了讓觀察者與被觀察者之間進行解耦。
UML圖:
角色說明:
Subject(抽象主題):被觀察者的一個抽象類,它會把所有觀察者的引用保存在一個集合里。抽象主題提供一個介面,可以增加和刪除觀察者對象。
ConcreteSubject(具體主題):具體的被觀察者。當具體被觀察者的狀態發生改變的時候,會給每一個註冊過的觀察者發送通知。
Observer(抽象觀察者):所有具體觀察者的一個抽象類,為所有的具體觀察者定義了一個介面:得到主題的通知時候更新自己。
ConcrereObserver(具體觀察者):抽象觀察者的具體實現。
我們看一下具體的例子:
上課鈴聲響起時候,老師與學生們的不同反應。
1、定義一個抽象主題:
該抽象主題定義了一些通用的方法,即具體主題裡面需要實現的。
//抽象被觀察者 public interface Observable { //添加觀察者 void addObserver(Observer observer); //移除觀察者 void deleteObserver(Observer observer); //通知觀察者 void notifyObserver(String msg); }
2、創建一個具體主題(上課鈴聲):
public class AlarmClock implements Observable { //保存觀察者對象 List<Observer> list = new ArrayList<>(); @Override public void addObserver(Observer observer) { list.add(observer); } @Override public void deleteObserver(Observer observer) { list.remove(observer); } /** * 通知觀察者 * @param msg */ @Override public void notifyObserver(String msg) { for (Observer observer : list) { observer.action(msg); } } }
3、創建抽象觀察者:
定義了所有具體觀察者需要實現的方法,聽到鈴聲後的行為
//抽象觀察者 public interface Observer { void action(String msg); }
4、創建具體觀察者:
public class Students implements Observer { String name; public Students(String name) { this.name = name; } @Override public void action(String msg) { System.out.println(msg + name + "開始聽課"); } } public class Teacher implements Observer { @Override public void action(String msg) { System.out.print(msg + "老師開始講課"); } }
6、實現:
Observable alarmClock = new AlarmClock(); Observer student1 = new Students("小屁孩"); Observer student2 = new Students("大屁孩"); Observer teacher = new Teacher(); //註冊觀察者 alarmClock.addObserver(student1); alarmClock.addObserver(student2); alarmClock.addObserver(teacher); //被觀察者通知已經註冊的觀察者 alarmClock.notifyObserver("上課鈴聲已經響了");
7、結果:
到這裡我們便實現了觀察者模式。
應用場景
- 當一個對象的改變需要通知其它對象改變時,而且它不知道具體有多少個對象有待改變時。
- 當一個對象必須通知其它對象,而它又不能假定其它對象是誰
- 跨系統的消息交換場景,如消息隊列、事件匯流排的處理機制。
優點
- 解除觀察者與主題之間的耦合。讓耦合的雙方都依賴於抽象,而不是依賴具體。從而使得各自的變化都不會影響另一邊的變化。
- 易於擴展,對同一主題新增觀察者時無需修改原有代碼。
缺點
- 依賴關係並未完全解除,抽象主題仍然依賴抽象觀察者。
- 使用觀察者模式時需要考慮一下開發效率和運行效率的問題,程式中包括一個被觀察者、多個觀察者,開發、調試等內容會比較複雜,而且在Java中消息的通知一般是順序執行,那麼一個觀察者卡頓,會影響整體的執行效率,在這種情況下,一般會採用非同步實現。
- 可能會引起多餘的數據通知。
JDK內部也內置了Observable(抽象被觀察者),Observer(抽象觀察者)這兩個類,我們也可以直接拿來用,具體可以去看看源碼。 Android中有很多地方也用到了觀察者模式:
- 點擊事件
- listView的刷新
- 廣播等等