目錄
* 前言 <https://www.cnblogs.com/yeya/p/11250217.html#前言>
* 觀察者模式 <https://www.cnblogs.com/yeya/p/11250217.html#觀察者模式>
* 定義 <https://www.cnblogs.com/yeya/p/11250217.html#定義>
* 通用類圖 <https://www.cnblogs.com/yeya/p/11250217.html#通用類圖>
* 實際例子 <https://www.cnblogs.com/yeya/p/11250217.html#實際例子>
* 總結 <https://www.cnblogs.com/yeya/p/11250217.html#總結>
* 優(yōu)點 <https://www.cnblogs.com/yeya/p/11250217.html#優(yōu)點>
* 缺點 <https://www.cnblogs.com/yeya/p/11250217.html#缺點>
* 參考: <https://www.cnblogs.com/yeya/p/11250217.html#參考>
前言
時間飛逝,轉眼初夏已過,尤記得以前讀大學的時候,夏季最快樂的時光就是和小伙伴們在球場上打完球后去校門附近的燒烤攤擼串喝酒,那種感覺真是大快人心,怎一個爽字了得。不過有時也會遇到特殊情況,在擼串時攤主突然告知要收攤,連忙向我們賠禮道歉,原因是城管將至。我們無奈只能中斷擼串過程,帶著無法盡興的郁悶心情離開.......
好吧,扯遠了,說那么多廢話也是想介紹兩個角色,城管和燒烤攤主,這兩個角色其實就相當于觀察者模式中的被觀察者和觀察者,他們的活動過程其實就類似于觀察者模式。
觀察者模式
開始介紹觀察者模式,毫無疑問,先說下它的定義。
定義
定義對象間一種一對多的依賴關系,使得每當一個對象改變狀態(tài),則所有依賴于它的對象都會得到通知并被自動更新。
其實就是發(fā)布-訂閱模式,在實際的項目中非常的常見,比如微信公眾號的消息推送就是觀察者模式的最直接的應用。
通用類圖
上面的類圖包含了四個角色,分別是:
*
Subject
抽象被觀察者:定義被觀察者必須實現的職責,它必須能夠動態(tài)地增加、取消觀察者。它一般是抽象類或者是實現類,僅僅完成作為被觀察者必須實現的職責:管理觀察者并通知觀察者。
*
Observer 抽象觀察者:為所有的具體觀察者定義一個接口,在得到主題通知時更新自己。
*
ConcreteSubject 具體被觀察者:定義被觀察者自己的業(yè)務邏輯,同時定義對哪些事件進行通知。
*
ConcreteObserver 具體觀察者:實現抽象觀察者角色所需要的更新接口,各個觀察者有自己的處理邏輯。
實際例子
講完了觀察者模式的角色后,我們用實戰(zhàn)例子來演示一下,就拿城管和小攤攤主舉例好了,城管對應著觀察者模式中的被觀察者,而攤主就對應著觀察者。OK,角色分配好了,我們開始寫代碼吧。
抽象被觀察者
public abstract class Subject { //定義一個觀察者數組 private List<Observer> obs = new
ArrayList<>(); //增加一個觀察者 public void addObserver(Observer o) { this.obs.add(o);
} //刪除一個觀察者 public void delObserver(Observer o) { this.obs.remove(o); }
//通知所有觀察者 public void notifyObservers() { for (Observer o : this.obs) {
o.update(); } } }
具體被觀察者
也就是城管,不知道英文怎么拼,用Police代替了,
public class Police extends Subject { public void chase(){
System.out.println("城管:我要來了,還不走"); // 通知所有觀察者 notifyObservers(); } }
抽象觀察者
public interface Observer { /** * 通知更新 * @param message */ void update(String
message); }
具體觀察者
public class Vendor implements Observer { private String name; private String
message; public Vendor(String name) { this.name = name; } @Override public void
update(String message) { System.out.println(name + " 收到: " + message); } }
場景類
最后用一個場景類驗證一下,
public class Client { public static void main(String[] args) { // 城管--被觀察者
Police police = new Police(); // 燒烤攤主--觀察者 Observer barbecueVendor = new
Vendor("燒烤攤主"); // 手抓餅攤主--觀察者 Observer cakeVendor = new Vendor("手抓餅攤主");
System.out.println("=======增加兩個觀察者=======");
police.addObserver(barbecueVendor); police.addObserver(cakeVendor);
police.chase(); System.out.println("=======刪除一個觀察者=======");
police.delObserver(cakeVendor); police.chase(); } }
定義一個城管對象和兩個攤主對象,然后執(zhí)行通知更新的操作,結果如下:
=======增加兩個觀察者======= 城管:我要來了,還不走 燒烤攤主 收到: 城管要來了,大家跑啊 手抓餅攤主 收到: 城管要來了,大家跑啊
=======刪除一個觀察者======= 城管:我要來了,還不走 燒烤攤主 收到: 城管要來了,大家跑啊
可以看到,我們的代碼能正常增刪觀察者角色,同時也能通知消息更新,也算是重現了了觀察者模式的流轉過程。
總結
優(yōu)點
1、觀察者和被觀察者之間抽象耦合。不管是增加觀察者還是被觀察者都非常容易擴展,而且在Java中都已經實現的抽象層級的定義,在系統擴展方面更是得心應手。
2、對象之間的保持高度的協作。當被觀察者發(fā)生變化時,所有被觀察者都會通知到,然后做出相應的動作。
缺點
1、如果觀察者太多,被觀察者通知觀察者消耗的時間很多,同時開發(fā)和調試會比較復雜,影響系統的性能。
2、在Java中消息的通知默認是順序執(zhí)行,當某一觀察者錯誤時就會導致系統卡殼,因此一般會采用異步方式。
參考:
《設計模式之禪》
熱門工具 換一換