設計模式之觀察者模式(Observer)

来源:https://www.cnblogs.com/chencarl/archive/2018/04/06/8727768.html
-Advertisement-
Play Games

觀察者模式通常的叫法叫做訂閱 發佈模式,類似於報刊雜誌的訂閱,觀察者和被觀察者就是讀者和郵局的關係,讀者先要在郵局訂閱想要的報刊,當報刊發行時,郵局會將報刊郵寄到讀者家裡。觀察者(Observer)和被觀察者(Listener)也是這種關係,Observer將自己attach到Listener中,當 ...


觀察者模式通常的叫法叫做訂閱-發佈模式,類似於報刊雜誌的訂閱,觀察者和被觀察者就是讀者和郵局的關係,讀者先要在郵局訂閱想要的報刊,當報刊發行時,郵局會將報刊郵寄到讀者家裡。觀察者(Observer)和被觀察者(Listener)也是這種關係,Observer將自己attach到Listener中,當Listener觸發時Notify所有Observer.

作用

在觀察者模式中,被觀察者維護觀察者對象的集合,當被觀察者對象變化時,它會通知觀察者。觀察者模式主要是用於解決對象之間一對多的關係。

類視圖

實現

class Observer 
{
public:
    virtual ~Observer() {};
    virtual void Update(const std::string &msg)= 0; 
protected:
    Observer(){};
};


class Listener
{
public:
    virtual ~Listener() {};
    void attach(Observer* obsvr) 
    {
        m_observers.push_back(obsvr);
    }
    void remove(Observer* obsvr)
    {
        m_observers.remove(obsvr);
    }
    void notify(const std::string &msg)
    {
        list<Observer*>::iterator iter = m_observers.begin();  
        for(; iter != m_observers.end(); iter++)  
            (*iter)->Update(msg); 
    }
private:  
    list<Observer* > m_observers; //觀察者鏈表 
};


class logRunner : public Listener
{
public:
    virtual ~logRunner(){};
    void addmsg(const std::string &msg)
    {
        nofity(msg);
    }
}

class logGui : public Observer
{
public:
    virtual ~Observer(){};
    void Update(const std::string &msg)
    {
        cout<< "Gui log show : "<< msg <<endl;
    }
}

class logFile : public Observer
{
public:
    virtual ~Observer(){};
    void Update(const std::string &msg)
    {
        cout<< "file log write : "<< msg <<endl;
    }
}

class logDebug : public Observer
{
public:
    virtual ~Observer(){};
    void Update(const std::string &msg)
    {
        cout<< "Debug log out : "<< msg <<endl;
    }
}


class logDataBase : public Observer
{
public:
    virtual ~Observer(){};
    void Update(const std::string &msg)
    {
        cout<< "DataBase log in : "<< msg <<endl;
    }
}

int main()
{
    logRunner Runner;
    logGui gGui;
    logFile gFile;
    logDebug gDebug;
    logDataBase gDataBase;
    
    Runner.attach(&gGui);
    Runner.attach(&gFile);
    Runner.attach(&gDebug);
    Runner.attach(&gDataBase);
    
    Runner.addmsg("app is setup");
}

Observer中update一般為純虛,通過子類各自實現,這裡只是保證調用的介面一致,Listener中的attach、remove、notify一般建議不進行虛化,子類不用關心其內部的聚合內容,通過調用notify實現消息分發即可。當然也可以虛化,將這一系列的操作放到子類進行實現。
調用者應該註意在多線程環境中的使用環境,做好數據的同步工作。

應用場景

  1. 當一個對象改變需要通知到其他對象,而我們不確定由多少對象需要通知時;
  2. 當一個對象必須通知其他對象,而不需要知道對象是什麼實現時;
  3. 對於一堆對象,包含同樣的狀態或同樣的數據,通過同一個條件進行更新時。

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 常用的一些快捷鍵: Windows + e 我的電腦Ctrl + Tab 網頁間不同頁面切換F2 重命名Ctrl+Shift+S 另存為 前端的一些常識:前端意義:將效果圖生成網頁網頁組成:文字、圖片、輸入框、視頻、音頻、超鏈接Web標準:Html 結構標準;Css 表現標準;Js 行為標準 瀏覽器 ...
  • 最近想用LayaBox做個小游戲,然而Laya本身不自帶構建工具。然後覺得寫模塊化的東西還是用webpack好使,用es6的語法也比較清晰。 於是就裝了webpack,只用babel-loader來編譯用es6寫的代碼。配置文件如下: 一開始我沒有設定mode,雖然我在babelrc裡面寫了comp ...
  • 一、對象冒充 其原理如下:構造函數使用 this 關鍵字給所有屬性和方法賦值(即採用類聲明的構造函數方式)。因為構造函數只是一個函數,所以可使 Parent 構造函數 成為 Children 的方法,然後調用它。Children 就會收到 Parent 的構造函數中定義的屬性和方法。原理:就是把 ... ...
  • Object構造函數 創建自定義對象最簡單的方式就是創建一個 Object 的實例,然後再為它添加屬性和方法: 缺點 代碼冗餘,會產生大量重覆代碼 無法識別對象(無法知道對象的類型) 對象字面量 對象字面量相比較於 Object 構造函數,代碼會比較直觀一些: 缺點 代碼冗餘,會產生大量重覆代碼 無 ...
  • 原生JavaScript實現頁面回到頂部的功能,如果想實現點擊一個按鈕讓滾動條回到最頂部的功能,首先可能就會想到它是從底部位置移動到頂部的位置 它是一個運動的過程,只要知道當前位置(current Position)和想要到達的位置(target Position)不就可以啦 只不過以前用的都是元素... ...
  • 迭代器在STL運用廣泛,類似容器的迭代已經成為其重要特性,而迭代器模式則是利用迭代器概念進行的抽象運用,迭代器模式運用廣泛和有用,因為其能夠不考慮數據的存儲方式,而是直接面對數據進行迭代,也就是說我們不用考慮集合是數組(或vector)、鏈表、棧還是隊列,而是通過統一的介面進行順序的訪問。 作用 迭 ...
  • 我有點像瘋子,一個人開了一天酒店,來寫這個。我發現我寫這個系列,閱讀的人很少。也許是程式員不重視思想的東西,也許是感覺我寫的很Low,無所謂,我只想告訴同行,程式員重在編程思想,有了編程思想技術的路才能走的更長更遠。我很孤獨,在自己的小世界里存活著。但是我也要耐著孤獨,向更好的方向發展需要孤獨,孤獨 ...
  • 進程的三態模型 細分進程狀態圖 進程的通信 互斥:一次只能供一個進程使用的資源。 同步:多個進程併發進行,可能需要等待。 生產者與消費者 PV操作 PV操作是實現進程同步與互斥的常用方法,在執行期間不可分割。P代表申請一個資源,V代表釋放一個資源。 P操作定義 :S1:=S1-1,若S>=0,則P操... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...