從未這麼明白的設計模式(二):觀察者模式

cover
<!-- more -->

本文原創地址,我的博客https://jsbintask.cn/2019/04/15/designpattern/observer/(食用效果最佳),轉載請註明出處!

前言

觀察者模式定義了對象間的一種一對多依賴關係,當一個對象狀態發生改變時,觀察者們都可以做出相應的更新,使得系統更易於擴展!
代碼地址:https://github.com/jsbintask22/design-pattern-learning

案例

  1. 小麗長得很漂亮,"天生麗質難自棄", 是一個不折不扣的"女神"。
  2. 小麗身邊有很多”備胎“,他們通過各種方式添加了小麗的微信,“小豪,小吳”都是其中之一。
  3. 小麗總是會在朋友圈發佈自己的各種生活狀態。
  4. ”備胎們“總是及時並且積極地和女神互動!
  5. 小麗發現”備胎“小豪不愛互動了,於是刪除了“備胎”小豪的微信。
  6. 小豪發現自己看不了女神動態了。最終死心!
  7. 小麗認識了新“備胎”小李,於是小李也添加了女神微信。
  8. 小麗發佈自己的朋友圈動態,小李也開始了互動!

上面這個過程我們可以抽象出來兩個主題,女神小麗,備胎小豪,小吳,小李,我們用代碼模擬這個追女神的過程。

代碼實現

V1.0

Beauty代表女神,LittleBoy表示備胎,他們時刻在關注着女神的朋友圈,希望獲得互動,代碼實現如下:
Observer
Observer

public class App {
    public static void main(String[] args) throws Exception{
        Beauty beauty = new Beauty();
        // 成功添加了女神微信
        LittleBoy littleBoy = new LittleBoy(beauty);

        // 開始查看女神朋友圈
        littleBoy.start();

        // 5s後,女神發佈了朋友圈。
        Thread.sleep(5000L);
        beauty.publishWechat();

        System.in.read();
    }
}

運行結果如下:
Observer
嗯!似乎很完美! 美中不足的是好像LittleBoy的run方法一直在輪詢查看女神朋友圈,它沒辦法做自己的事情了:
Observer
這樣下去很快他就會失去和女神互動的耐心! 所以我們稍微修改下,讓這段代碼看起來更加”智能”。

V2.0

爲了不讓LittleBoy一直輪詢查看女神狀態,我們可以修改爲女神主動推送她的狀態給“備胎們”,這樣他們就可以去做其他事情了!
Observer
Observer

public class App {
    public static void main(String[] args) throws Exception{
        Beauty beauty = new Beauty();
        LittleBoy littleBoy = new LittleBoy();
        // 添加女神微信
        beauty.littleBoy = littleBoy;

        // 發佈動態
        beauty.publishWechat();
    }
}

Observer
嗯!這樣一來就智能多了! 女神更新朋友圈後主動推送消息給備胎!備胎不用死守着女神的朋友圈,而是收到消息後自動去查看。所以他們的關係是這樣了:
Observer
但是,現在又有一個新問題!這段代碼好像顯得不夠面向對象,不夠專業。

  1. 女神如果想要新加一個舔狗,就要動女神的邏輯代碼。
  2. 新加了一個備胎之後,不知道如何把自己的動態分享給他(例如上面的active方法,可能“新備胎”沒有)。
  3. 備胎突然舔不動了怎麼辦了,他不想再收到女神動態了!

既然這樣,我們把這段代碼修改下,讓它變得“靈活”,更加“面向對象”些!

V3.0

既然要靈活,面向對象。我們這麼處理:將女神抽象爲一個接口,並且她要能夠刪除備胎,添加備胎,通知備胎。同時我們將備胎抽象爲一個接口,他能夠在收到女神通知後及時做出反應!
Beauty:
Observer
LittleBoy:
Observer
它們分別有一個實現:BeautyImplLittleBoyImpl:
Observer
測試代碼:

public class App {
    public static void main(String[] args) {
        Beauty beauty = new BeautyImpl();
        LittleBoy boy1 = new LittleBoyImpl("小豪");
        LittleBoy boy2 = new LittleBoyImpl("小吳");

        // 添加兩個備胎
        beauty.addLittleBoy(boy1);
        beauty.addLittleBoy(boy2);

        // 發佈朋友圈
        beauty.publishWechat("最美的不是下雨天,是曾和你一起躲過雨的屋檐!");

        // 刪除備胎1,並且新添加了備胎3
        beauty.removeLittleBoy(boy1);
        beauty.addLittleBoy(msg -> {
            System.out.println(" 小李:哎喲,不錯哦!");
        });

        // 再次發佈朋友圈
        beauty.publishWechat("哪裏有彩虹告訴我。。。");
    }
}

Observer
嗯!通過面向接口編程完美的解決了上面的問題,現在女神這個類已經變得非常靈活了,仔細觀察,我們已經把我們上面的說的案例完全實現!現在它們的關係是這樣的:
Observer

擴展

觀察者模式這種發佈與訂閱的思想使用的非常廣泛,基本各個框架,思想都能看到它的身影,而jdk中也已經抽象了觀察與被觀察者:
java.util.Observer表示觀察者:
Observer
java.util.Obserable表示被觀察者(例如上面的女神):
Observer
然後美中不足的是,jdk把Observable設計成了一個類,這並不利於擴展! 當然我們仍然可以自己實現接口,就像上面所做的。

總結

我們從觀察者模式特點入手,通過一個案例,一步一步完善了觀察着的寫法,特點!組後介紹了jdk總已有的實現!

關注我,這裏只有乾貨!

同系列文章:
從未這麼明白的設計模式(一):單例模式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章