java設(shè)計(jì)模式之觀察者模式

一、觀察者模式

當(dāng)對(duì)象中存在一對(duì)多的關(guān)系時(shí),就需要使用這種模式。比如說(shuō)一個(gè)對(duì)象發(fā)生改變時(shí),會(huì)通知到依賴(lài)它的對(duì)象。

介紹
  • 意圖:定義對(duì)象之間一對(duì)多的依賴(lài)關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),會(huì)通知到其它依賴(lài)該對(duì)象的行為。
  • 主要解決:一個(gè)對(duì)象狀態(tài)改變給其他對(duì)象通知的問(wèn)題,而且要考慮到易用和低耦合,保證高度的協(xié)作。
  • 如何解決:采用面向?qū)ο蟮募夹g(shù),可以將這種關(guān)系弱化。
  • 關(guān)鍵代碼:在被訂閱類(lèi)里面采用一個(gè)集合來(lái)存放觀察者,并且在狀態(tài)改變時(shí)一一通知他們?nèi)ジ隆?/li>
  • 應(yīng)用實(shí)例:1.對(duì)于在訂閱了微信公眾號(hào)某個(gè)主題的用戶來(lái)說(shuō),每當(dāng)公眾號(hào)有發(fā)布新的內(nèi)容時(shí),會(huì)自動(dòng)的將內(nèi)容及時(shí)推送到用戶;2.在初中的教室上課,當(dāng)下課鈴聲響起的時(shí)候,學(xué)生們會(huì)主動(dòng)收拾書(shū)包準(zhǔn)備下課回家吃飯了;3.在某會(huì)議上面,領(lǐng)導(dǎo)召集了負(fù)責(zé)各個(gè)業(yè)務(wù)模塊的子領(lǐng)導(dǎo),及時(shí)傳達(dá)了某些核心思想,參與了此次會(huì)議的小負(fù)責(zé)人會(huì)通知到各個(gè)下屬。
  • 注意事項(xiàng):1.Java中已經(jīng)有了對(duì)于觀察者的支持類(lèi)。2.避免循環(huán)引用。3.如果順序執(zhí)行,某一個(gè)觀察者執(zhí)行時(shí)發(fā)生了錯(cuò)誤,會(huì)導(dǎo)致卡克,一般采取異步的方式去執(zhí)行。
演示

下面通過(guò)一個(gè)小的demo來(lái)展示一下觀察者模式的使用場(chǎng)景。

  • 微信公眾號(hào)推送文章
    首先先來(lái)明確下各個(gè)扮演的角色,對(duì)于訂閱了某個(gè)公眾號(hào)的用戶來(lái)說(shuō),他們屬于觀察者,而公眾號(hào)的文章的發(fā)布屬于被觀察者。明確了這一點(diǎn)后,下面就比較好擼代碼了。
    1、定義被觀察者的主要方法,采取接口來(lái)定義

     /**
      * 微信主題的接口  即被觀察著  他會(huì)有三個(gè)方法  
     * @author rain
     *
     */
    public interface IWxServerSubject {
    
          void attach(IObserver observer);
    
          void detach(IObserver observer);
    
          void updateObserver();
    }
    

2 、定義抽象的觀察者接口

    /**
     * 觀察者  訂閱了微信主題的觀察者
     * @author rain
     *
     */
    public interface IObserver {

        void receiveContent(String info);
    }

`3、實(shí)現(xiàn)具體的被觀察者

public class IWxSubjectImpl implements IWxServerSubject{

        //觀察者列表  訂閱了微信公眾號(hào)的讀者
        private List<IObserver> observers = new ArrayList<>();
        private String submitContent;

        @Override
        public void attach(IObserver observer) {
            observers.add(observer);
        }

        //一個(gè)信號(hào)  即發(fā)布了新的文章
        public void submitContent(String content){
            this.submitContent = content;
            updateObserver();
        }

        @Override
        public void detach(IObserver observer) {
            if(observers.contains(observer)){
              observers.remove(observer);
            }
        }

        @Override
        public void updateObserver() {
            for (IObserver iObserver : observers) {
                iObserver.receiveContent(submitContent);
            }
        }
    }

4、定義一個(gè)具體的觀察者

    /**
     * 讀者  訂閱了微信公眾號(hào)的  觀察者
     * @author rain
     *
     */
    public class ReaderObsever implements IObserver{

        private String name;

        public  ReaderObsever(String name) {
            this.name = name;
        }
        @Override
        public void receiveContent(String info) {
            System.out.println(name +" ,請(qǐng)注意:Rain發(fā)布了新的微信公眾號(hào)文章---"+info);
        }

        public String getName(){
    
            return name;
        }

    }

5、來(lái)個(gè)測(cè)試類(lèi)模擬一下吧

public class Test {

     public static void main(String[] args) {
    
    IWxServerSubject subject = new IWxSubjectImpl();
    
    //創(chuàng)建了四個(gè)讀者  并且都關(guān)注了該公眾號(hào)的  只有趙六沒(méi)有關(guān)注  
    ReaderObsever reader1 = new ReaderObsever("張三");
    ReaderObsever reader2 = new ReaderObsever("李四");
    ReaderObsever reader3 = new ReaderObsever("王五");
    
    //訂閱了該公眾號(hào)的讀者  即觀察者角色
    subject.attach(reader1);
    subject.attach(reader2);
    subject.attach(reader3);
    
    //公眾號(hào)發(fā)布了文章了
    
    ((IWxSubjectImpl)subject).submitContent("觀察者設(shè)計(jì)模式開(kāi)始啦?。?!");
    


    }

}

運(yùn)行一下:


模擬觀察者.png

可以看到,訂閱過(guò)該公眾號(hào)的用戶確實(shí)收到了新發(fā)布的文章,good。。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容