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

前言

時間飛逝默勾,轉(zhuǎn)眼初夏已過碉渡,尤記得以前讀大學(xué)的時候,夏季最快樂的時光就是和小伙伴們在球場上打完球后去校門附近的燒烤攤擼串喝酒灾测,那種感覺真是大快人心,怎一個爽字了得垦巴。不過有時也會遇到特殊情況媳搪,在擼串時攤主突然告知要收攤,連忙向我們賠禮道歉骤宣,原因是城管將至秦爆。我們無奈只能中斷擼串過程,帶著無法盡興的郁悶心情離開.......

好吧憔披,扯遠(yuǎn)了等限,說那么多廢話也是想介紹兩個角色,城管和燒烤攤主芬膝,這兩個角色其實就相當(dāng)于觀察者模式中的被觀察者和觀察者望门,他們的活動過程其實就類似于觀察者模式。

觀察者模式

開始介紹觀察者模式锰霜,毫無疑問筹误,先說下它的定義。

定義

定義對象間一種一對多的依賴關(guān)系癣缅,使得每當(dāng)一個對象改變狀態(tài)厨剪,則所有依賴于它的對象都會得到通知并被自動更新。

其實就是發(fā)布-訂閱模式友存,在實際的項目中非常的常見祷膳,比如微信公眾號的消息推送就是觀察者模式的最直接的應(yīng)用。

通用類圖

image

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

  • Subject 抽象被觀察者:定義被觀察者必須實現(xiàn)的職責(zé)直晨,它必須能夠動態(tài)地增加、取消觀察者膨俐。它一般是抽象類或者是實現(xiàn)類抡秆,僅僅完成作為被觀察者必須實現(xiàn)的職責(zé):管理觀察者并通知觀察者。

  • Observer 抽象觀察者:為所有的具體觀察者定義一個接口吟策,在得到主題通知時更新自己儒士。

  • ConcreteSubject 具體被觀察者:定義被觀察者自己的業(yè)務(wù)邏輯,同時定義對哪些事件進行通知檩坚。

  • ConcreteObserver 具體觀察者:實現(xiàn)抽象觀察者角色所需要的更新接口着撩,各個觀察者有自己的處理邏輯诅福。

實際例子

講完了觀察者模式的角色后,我們用實戰(zhàn)例子來演示一下拖叙,就拿城管和小攤攤主舉例好了氓润,城管對應(yīng)著觀察者模式中的被觀察者,而攤主就對應(yīng)著觀察者薯鳍。OK咖气,角色分配好了,我們開始寫代碼吧挖滤。

抽象被觀察者

public abstract class Subject {
    //定義一個觀察者數(shù)組
    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í)行通知更新的操作乳幸,結(jié)果如下:

=======增加兩個觀察者=======
城管:我要來了,還不走
燒烤攤主 收到: 城管要來了钧椰,大家跑啊
手抓餅攤主 收到: 城管要來了粹断,大家跑啊
=======刪除一個觀察者=======
城管:我要來了,還不走
燒烤攤主 收到: 城管要來了嫡霞,大家跑啊

可以看到姿染,我們的代碼能正常增刪觀察者角色,同時也能通知消息更新秒际,也算是重現(xiàn)了了觀察者模式的流轉(zhuǎn)過程悬赏。

總結(jié)

優(yōu)點

1、觀察者和被觀察者之間抽象耦合娄徊。不管是增加觀察者還是被觀察者都非常容易擴展闽颇,而且在Java中都已經(jīng)實現(xiàn)的抽象層級的定義,在系統(tǒng)擴展方面更是得心應(yīng)手寄锐。

2兵多、對象之間的保持高度的協(xié)作。當(dāng)被觀察者發(fā)生變化時橄仆,所有被觀察者都會通知到剩膘,然后做出相應(yīng)的動作。

缺點

1盆顾、如果觀察者太多怠褐,被觀察者通知觀察者消耗的時間很多,同時開發(fā)和調(diào)試會比較復(fù)雜您宪,影響系統(tǒng)的性能奈懒。

2奠涌、在Java中消息的通知默認(rèn)是順序執(zhí)行,當(dāng)某一觀察者錯誤時就會導(dǎo)致系統(tǒng)卡殼磷杏,因此一般會采用異步方式溜畅。

參考:

《設(shè)計模式之禪》

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市极祸,隨后出現(xiàn)的幾起案子慈格,更是在濱河造成了極大的恐慌,老刑警劉巖遥金,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件浴捆,死亡現(xiàn)場離奇詭異,居然都是意外死亡汰规,警方通過查閱死者的電腦和手機汤功,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進店門物邑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來溜哮,“玉大人,你說我怎么就攤上這事色解∶ぃ” “怎么了?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵科阎,是天一觀的道長述吸。 經(jīng)常有香客問我,道長锣笨,這世上最難降的妖魔是什么蝌矛? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮错英,結(jié)果婚禮上入撒,老公的妹妹穿的比我還像新娘。我一直安慰自己椭岩,他們只是感情好茅逮,可當(dāng)我...
    茶點故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著判哥,像睡著了一般献雅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上塌计,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天挺身,我揣著相機與錄音,去河邊找鬼锌仅。 笑死瞒渠,一個胖子當(dāng)著我的面吹牛良蒸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播伍玖,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼嫩痰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了窍箍?” 一聲冷哼從身側(cè)響起串纺,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎椰棘,沒想到半個月后纺棺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡邪狞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年祷蝌,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帆卓。...
    茶點故事閱讀 38,683評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡巨朦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出剑令,到底是詐尸還是另有隱情糊啡,我是刑警寧澤,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布吁津,位于F島的核電站棚蓄,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏碍脏。R本人自食惡果不足惜梭依,卻給世界環(huán)境...
    茶點故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望典尾。 院中可真熱鬧役拴,春花似錦、人聲如沸急黎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽勃教。三九已至淤击,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間故源,已是汗流浹背污抬。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人印机。 一個月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓矢腻,卻偏偏與公主長得像,于是被迫代替她去往敵國和親射赛。 傳聞我的和親對象是個殘疾皇子多柑,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,566評論 2 349

推薦閱讀更多精彩內(nèi)容