java觀察者模式:如何通知事物的變化

517871628511674_.pic.jpg

這是我參與8月更文挑戰的第9天,活動詳情查看:8月更文挑戰java

歡迎來到今天的學習,今天咱們一塊兒來學習下使用頻率很高且實踐比較多的一種模式----觀察者模式。多嘮叨幾句,我本月將會對java的設計模式精講,歡迎點擊頭像,關注個人專欄,我會持續更新,加油!設計模式

系列文章:微信

設計模式之單例模式markdown

設計模式之工廠模式數據結構

設計模式之建造者模式框架

設計模式之代理模式異步

設計模式之訪問者模式ide

設計模式之適配器模式post

設計模式之命令者模式性能

java狀態模式 | 隨時隨地監控狀態改變

...持續更新中

話很少說,進入正題

觀察者模式

觀察者模式是一種很是流行的設計模式,也有人稱之爲訂閱-發佈模式,我我的認爲都是一種思想,就是一對象當中,任何的改變,都能被監聽到,識別到,而後去通知改變,這個行爲也能夠稱之爲「事件」,觀察者經過處理每個事件來完成自身的操做處理

觀察者模式的原始定義是:定義對象之間的一對多依賴關係,這樣當一個對象改變狀態時,它的全部依賴項都會自動獲得通知和更新。

注意:該定義當中,對象之間的是一對多,那麼這個一就是觀察者,只有一個觀察者在觀察動態,多即是指被觀察者。咱們還能夠稱觀察者模式爲如下幾種叫法,不過無論怎麼叫,本質都是觀察者模式的思想

  • 事件發佈,事件監聽

  • 發佈者-訂閱者

  • 生產者-消費者

這種模式在各類框架源碼當中也家常便飯,很適合在實踐中運用與巧妙處理。

我之前寫過一篇乾貨實戰文章,就是利用Spring當中的監聽來完成的,有興趣的能夠看下:

乾貨!SpringBoot利用監聽事件,實現異步操做

迴歸正題,下面看下,觀察者模式的圖(圖片來源於網路)

image.png

從上圖中,咱們能看出觀察者模式包含的四個關鍵角色:

1 、發佈者(Publisher),也被叫做主題、被訂閱者、被觀察者等

二、 具體發佈者(PublisherImpl),實現了發佈者定義的方法的具體實現類

三、訂閱者(Observer):也叫做觀察者,它會存儲一個註冊列表,用於存放訂閱者。當發佈者發佈消息或事件時,會通知到訂閱者進行處理。

四、 具體訂閱者(ObserverImpl):實現具體定義的方法操做。

接下來咱們經過一個場景和代碼來讓你深刻理解下:

場景分析及代碼展現

使用場景分析:

咱們拿微信公衆號推文場景來展現下,咱們都知道咱們的公衆號推文文章只會推送給關注我公衆號的人,那麼,假如我今天發表一篇名爲「java觀察者模式」一篇推文,張三,李四,王五關注了個人公衆號,那麼我點擊發布,就會往他們的微信上推。

咱們首先定義觀察者 ArticleObserver。它只有一個 send 方法,當有文章 Article 發送過來時就會調用該方法。

public interface ArticleObserver {
    void send(Articl m);
}
複製代碼

接着再定義文章的具體數據結構,這裏使用一個 content 文章內容。

public class Articl {
    final String content;
    public Articl (String m) {
        this.content = m;
    }
    public String getContent() {
        return content;
    }
}
複製代碼

而後,再來定義一個被觀察者 Subject ,它定義了三個方法:增長觀察者方法 attach、刪除觀察者方。

public interface Subject {
    void attach(ArticleObserver a);  //增長觀察者
    void detach(ArticleObserver a);  //刪除觀察者
    
    void notifySend(Article m);    //異步發送推文
}
複製代碼

再接下來,實現 Subject 的具體發佈者類 ArticlePublisher,它持有一組觀察者 ArticleObserver 實例,能夠經過 attach 和 detach 接口方法新增和刪除觀察者,異步通知發送方法 notifySend

public class ArticlePublisher implements Subject {
    private List<ArticleObserver> observers = new ArrayList<>();
    @Override
    public void attach(ArticleObserver o) {
        observers.add(o);
    }
    @Override
    public void detach(ArticleObserver o) {
        observers.remove(o);
    }
    
    @Override
    public void notifySend(Articl m) {
        observers.forEach(x->x.sed(m));
    }
}
複製代碼

最後,咱們實現三個具體訂閱者類(張三,李四,王五),它們都實現(關注了該公衆號)了 ArticleObserver 接口,分別要發送到三者微信當中。

//張三訂閱
public class ZhangSanSubscriber implements ArticleObserver {
    @Override
    public void send(Articl a) {
        System.out.println("ZhangSanSubscriber 看到 :: " + a.getContent());
    }
}

//李四訂閱
public class LisiSubscriber implements ArticleObserver {
    @Override
    public void send(Articl a) {
        System.out.println("LisiSubscriber 看到 :: " + a.getContent());
    }
}

//王五訂閱
public class WangwuSubscriber implements ArticleObserver {
    @Override
    public void send(Articl a) {
        System.out.println("WangwuSubscriber 看到 :: " + a.getContent());
    }
}
複製代碼

單元測試下:

public class Client {
    public static void main(String[] args) {
        ArticleObserver zhangSan = new ZhangSanSubscriber();
        ArticleObserver liSi = new LisiSubscriber();
        ArticleObserver wangWu = new WangwuSubscriber();
        Subject p = new ArticlePublisher();
        
        // 增長訂閱,將相應訂閱者添加進去(集合)
        p.attach(zhangSan);
        p.attach(liSi);
        p.attach(wangWu);
        
        //發送推文
        p.notifySend(new Articl("java觀察者模式")); 
    }
}

//輸出結果
ZhangSanSubscriber 看到 :: java觀察者模式
LisiSubscriber     看到 :: java觀察者模式
WangwuSubscriber   看到 :: java觀察者模式

注意,我這裏只是用了一篇文章(發佈對象),能夠多種。
複製代碼

OK,代碼到這裏就結束了。

上面的代碼實現很是簡單,可是充分體現了觀察者模式的使用場景。觀察者模式使用場景的特色在於找到合適的被觀察者,定義一個通知列表,將須要通知的對象放到這個通知列表中,當被觀察者須要發起通知時,就會通知這個列表中的全部「人」

總結

使用觀察者模式的優勢:

  • 由利用代碼擴展性的提高,因爲觀察者和被觀察之間是抽象耦合,因此擴展性較強

  • 下降系統與系統之間的耦合性,好比,創建訂閱者集合,能夠隨時添加或者刪除該集合當中的某一元素。

有褒有貶:

我我的理解,會下降性能,觀察者模式一般須要事件觸發,當觀察者對象越多時,被觀察者須要通知觀察者所花費的時間也會越長,這樣會在某種程度上影響程序的效率。

看到這裏可能會有夥伴問了,爲何使用觀察者模式?,我認爲有如下兩點:

一、爲了方便捕獲觀察對象的變化並及時作出相應的操做,好比快遞的狀態要及時變動等。

二、上面也說到了,爲了提升代碼的擴展性

弦外之音

感謝你的閱讀,若是你感受學到了東西,麻煩您點贊,關注。

我已經將本章收錄在專題裏,點擊下方專題,關注專欄,我會天天發表乾貨,本月我會持續輸入設計模式。

加油! 咱們下期再見!

相關文章
相關標籤/搜索