設計模式:觀察者模式 ——— 城管來了,攤主快跑

今天學習設計模式系列的觀察者模式設計模式

前言

時間飛逝,轉眼初夏已過,尤記得之前讀大學的時候,夏季最快樂的時光就是和小夥伴們在球場上打完球后去校門附近的燒烤攤擼串喝酒,那種感受真是大快人心,怎一個爽字了得。不過有時也會遇到特殊狀況,在擼串時攤主忽然告知要收攤,連忙向咱們賠禮道歉,緣由是城管將至。咱們無奈只能中斷擼串過程,帶着沒法盡興的鬱悶心情離開.......數組

好吧,扯遠了,說那麼多廢話也是想介紹兩個角色,城管和燒烤攤主,這兩個角色其實就至關於觀察者模式中的被觀察者和觀察者,他們的活動過程其實就相似於觀察者模式。bash

觀察者模式

開始介紹觀察者模式,毫無疑問,先說下它的定義。微信

定義

定義對象間一種一對多的依賴關係,使得每當一個對象改變狀態,則全部依賴於它的對象都會獲得通知並被自動更新。異步

其實就是發佈-訂閱模式,在實際的項目中很是的常見,好比微信公衆號的消息推送就是觀察者模式的最直接的應用。ide

通用類圖

上面的類圖包含了四個角色,分別是:

  • Subject 抽象被觀察者:定義被觀察者必須實現的職責,它必須可以動態地增長、取消觀察者。它通常是抽象類或者是實現類,僅僅完成做爲被觀察者必須實現的職責:管理觀察者並通知觀察者。性能

  • Observer 抽象觀察者:爲全部的具體觀察者定義一個接口,在獲得主題通知時更新本身。學習

  • ConcreteSubject 具體被觀察者:定義被觀察者本身的業務邏輯,同時定義對哪些事件進行通知。this

  • ConcreteObserver 具體觀察者:實現抽象觀察者角色所須要的更新接口,各個觀察者有本身的處理邏輯。spa

實際例子

講完了觀察者模式的角色後,咱們用實戰例子來演示一下,就拿城管和小攤攤主舉例好了,城管對應着觀察者模式中的被觀察者,而攤主就對應着觀察者。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();
    }
}
複製代碼

定義一個城管對象和兩個攤主對象,而後執行通知更新的操做,結果以下:

=======增長兩個觀察者=======
城管:我要來了,還不走
燒烤攤主 收到: 城管要來了,你們跑啊
手抓餅攤主 收到: 城管要來了,你們跑啊
=======刪除一個觀察者=======
城管:我要來了,還不走
燒烤攤主 收到: 城管要來了,你們跑啊
複製代碼

能夠看到,咱們的代碼能正常增刪觀察者角色,同時也能通知消息更新,也算是重現了了觀察者模式的流轉過程。

總結

優勢

一、觀察者和被觀察者之間抽象耦合。不論是增長觀察者仍是被觀察者都很是容易擴展,並且在Java中都已經實現的抽象層級的定義,在系統擴展方面更是駕輕就熟。

二、對象之間的保持高度的協做。當被觀察者發生變化時,全部被觀察者都會通知到,而後作出相應的動做。

缺點

一、若是觀察者太多,被觀察者通知觀察者消耗的時間不少,同時開發和調試會比較複雜,影響系統的性能。

二、在Java中消息的通知默認是順序執行,當某一觀察者錯誤時就會致使系統卡殼,所以通常會採用異步方式。

參考:

《設計模式之禪》

相關文章
相關標籤/搜索