1. 程式人生 > >設計模式那點事–觀察者模式

設計模式那點事–觀察者模式

簡單說吧,該模式就只有兩種角色,觀察者物件(主題)和被觀察者物件(觀察者)。主題接收被觀察者,有更新就通知被觀察者。根據依賴倒轉原則高內聚低耦合的目標,我們分別對此增加兩個抽象介面。

概念:
    觀察者模式(Observer),又稱釋出\訂閱模式(Publish\Subscribe)。它定義了一種一對多的依賴關係,讓多個觀察者物件同時監聽某一個主題物件。這個主題物件在狀態發生變化時,會通知所有觀察者物件,使它們能夠自動更新自己。

例子:
    一個鮮活簡單的例子總能讓人輕鬆地理解晦澀的概念。我們來看看一個關於汽車零件更換的例子。
    大家應該有聽說過吧,日本豐田(Toyota)車廠先前由於油門踏板問題,宣佈在美國、歐洲和中國回收逾9百萬輛私家車及貨車,並作零件的更換。這次事件無疑對豐田品牌造成了重大的打擊。
    假設豐田的油門踏板的生產廠商和BMW,Ferrali和Benz一樣,當油門踏板出現問題時,油門踏板廠商會發出一個正式的零件更換通知書,以上所有品牌的汽車都會收到同樣的更新通知:更換油門踏板零件,以保證使用者使用車輛的安全。
    以上可看出,油門踏板廠商發出通知更新,所有的汽車供應商就會收到通知並進行更新,就是觀察者模式。

角色:
    簡單說吧,該模式就只有兩種角色,觀察者物件(主題)和被觀察者物件(觀察者)。主題接收被觀察者,有更新就通知被觀察者。根據依賴倒轉原則高內聚低耦合的目標,我們分別對此增加兩個抽象介面。
1. 抽象主題(Subject):它把所有對觀察者物件的引用儲存在一個聚集裡,每個主題都可以有任何數量的觀察者。抽象主題提供一個介面,可以增加和刪除觀察者物件;
2. 具體主題(ConcreteSubject):將有關狀態存入具體觀察者物件;在具體主題的內部狀態改變時,給所有登記過的觀察者發出通知。這裡可指油門踏板廠商;
3. 抽象觀察者(Observer):為所有的具體觀察者定義一個介面,在得到主題的通知時更新自己;
4. 具體觀察者(ConcreteObserver):實現抽象觀察者角色所要求的更新介面,以便使本身的狀態與主題的狀態相協調。這裡可指BMW,Ferrali和Benz。

UML圖:
這裡寫圖片描述

程式碼:

#pragma warning(disable:4786)

#include<iostream>
#include <vector>
#include <list>
#include <string>

using namespace std;

//具體觀察者結構體
typedef struct ObserverItems
{
    string strName;
    Observer* pObserver;
}ObserverSets;

//抽象觀察者
class Observer
{
public:
    virtual
void Update()=0; }; //抽象通知者 class Notice { public: virtual void AddObserver(ObserverSets* ob)=0; virtual void RemoveObserver(ObserverSets* ob)=0; virtual void Notify()=0; }; //具體通知者 class ConcreteNotice:public Notice { public: virtual ~ConcreteNotice() { list<ObserverSets*>::iterator stIter; for (stIter=observers.begin(); stIter!=observers.end(); stIter++) { if ((*stIter)->pObserver!=NULL) { delete (*stIter)->pObserver; (*stIter)->pObserver=NULL; } if ((*stIter)!=NULL) { delete (*stIter); (*stIter)=NULL; } } } public: string getState() { return m_noticeState; } void setState(string strState) { m_noticeState = strState; } public: //增加觀察者 void AddObserver(ObserverSets* ob) { observers.push_back(ob); } //去除觀察者 void RemoveObserver(ObserverSets* ob) { list<ObserverSets*>::iterator stIter; for (stIter=observers.begin(); stIter!=observers.end(); ) { if ((*stIter)->strName==ob->strName) { observers.erase(stIter); break; } else { ++stIter; } } } //通知更新 void Notify() { list<ObserverSets*>::iterator stIter; for (stIter=observers.begin(); stIter!=observers.end(); stIter++) { (*stIter)->pObserver->Update(); } } private: string m_noticeState; list<ObserverSets*> observers; }; //具體觀察者 class ConcreteObserver:public Observer { public: ConcreteObserver(ConcreteNotice* notice, string name) { this->m_Notice = notice; this->m_strName = name; } void Update() { m_strObserverState = m_Notice->getState(); cout<<"通知:"<<m_strName<<" 要更換:"<<m_strObserverState<<endl; } private: string m_strName; string m_strObserverState; ConcreteNotice* m_Notice; }; void main() { ConcreteNotice* notice = new ConcreteNotice; ObserverSets* pObItem = new ObserverSets; Observer* pOb=NULL; //新增BMW車觀察者 pOb = new ConcreteObserver(notice, "BMW車"); pObItem->pObserver = pOb; pObItem->strName = "BMW車"; notice->AddObserver(pObItem); //新增Ferrali車觀察者 pObItem = new ObserverSets; pOb = new ConcreteObserver(notice, "Ferrali車"); pObItem->pObserver = pOb; pObItem->strName = "Ferrali車"; notice->AddObserver(pObItem); //新增Benz車觀察者 pObItem = new ObserverSets; pOb = new ConcreteObserver(notice, "Benz車"); pObItem->pObserver = pOb; pObItem->strName = "Benz車"; notice->AddObserver(pObItem); //去除Benz車觀察者 notice->RemoveObserver(pObItem); notice->setState("輪胎"); notice->Notify(); delete notice; notice = NULL; return; }

發散:
    我們知道實現C++的多型有三種方法:函式過載,模板函式和虛擬函式。虛擬函式實現的多型稱為動態多型,上面程式碼有以下特點:
1. 子類的物件轉換給父類的物件,我們稱為向上轉型。它是安全的,自動完成,並且會丟失子型別的資訊;
2. 為了解決子型別資訊丟失的問題(子類物件轉換給父類),父類必須實現了一個虛擬函式;
3. 子類有完全相同的函式,覆蓋重寫父類的虛擬函式,這樣便能實現動態多型了(否則只能用指標或引用了)。

應用場景:
1. 當一個物件改變的時候同時需要改變其他物件,而且也可以不知道具體有多少物件有待改變;
2. 物件僅需要將自己的更新通知給其他物件而不需要知道其他物件的細節。

優點:
1. Subject在傳送廣播通知的時候,無須指定具體的Observer,Observer可以自己決定是否要訂閱Subject的通知;
2. 高內聚、低耦合,可各自獨立改變。

缺陷:
1. 鬆偶合導致程式碼關係不明顯,有時可能難以理解;
2. 如果一個Subject被大量Observer訂閱的話,在廣播通知的時候可能會有效率問題。

相關推薦

設計模式觀察模式

簡單說吧,該模式就只有兩種角色,觀察者物件(主題)和被觀察者物件(觀察者)。主題接收被觀察者,有更新就通知被觀察者。根據依賴倒轉原則高內聚低耦合的目標,我們分別對此增加兩個抽象介面。 概念:     觀察者模式(Observer),又稱釋出\訂閱模式

設計模式--策略模式

簡化 cas enter ext font 想要 fonts 對象創建 客戶 概念: 策略模式定義了一系列的算法,分別封裝起來,讓它們之間能夠相互替換。此模式讓算法的變化,不會影響到使用算法的客戶。策略,實質上指的是算法。 樣例

設計模式—模板模式

概念:   模板模式定義了一個操作中的演算法骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟。   模板模式是非常常用和結構簡單的行為型設計模式,就連剛開始學習面向物件繼承和多型知識的程式設計師也會不

設計模式(一)觀察模式

針對 ray 需求 als bool 模式 null rri 主動 觀察者模式 定義了對象之間的一對多的依賴,這樣一來,當一個對象狀態改變時,他的 多有依賴都會受到通知並自動更新。 本例為一個溫度基站,和三個終端。溫度基站為廣播類WeatherData,三個終端監聽者類分別

C#設計模式之十六觀察模式(Observer Pattern)【行為型】

ngx 現實生活 松耦合 mon html 機制 account current 很好 原文:C#設計模式之十六觀察者模式(Observer Pattern)【行為型】一、引言 今天是2017年11月份的最後一天,也就是2017年11月30日,利用今天再寫一個模式,爭取

[轉] 淺析JavaScript設計模式——發布-訂閱/觀察模式

div 函數 ons class esp 了解 寵物 是我 ring 前一段時間一直在寫CSS3的文章 一直都沒寫設計模式 今天來寫寫大名鼎鼎觀察者模式 先畫張圖 觀察者模式的理解 我覺得還是發布-訂閱模式的叫法更容易我們理解 (不過也有的書上認為它們是兩種模式&h

設計模式(二)—— 觀察模式

pda 發出 dex obs index observe target 獲取 委托事件 觀察者模式類似出版社與訂閱者的關系,訂閱者能夠收到出版社發出的消息,可以取消訂閱。出版社在觀察者模式中稱為主題(Subject)訂閱者稱為觀察者(Observer)。 主

設計模式真香筆記-觀察模式

觀察者模式的介紹 觀察者模式:物件之間一對多依賴,當一個物件改變狀態的時候,它的所有依賴都會收到通知並且自動更新。 這樣說可能有些人不能理解,我們來舉個生動形象的例子: 許多人以前會經常訂閱雜誌,雜誌社會定期發雜誌給訂閱者,當然他也可以取消訂閱,那麼雜誌社就不會繼續發雜誌給訂

設計模式(18)觀察模式

模式介紹 觀察者模式試圖允許物件在其內部狀態改變時通知觀察者。 這意味著單個物件需要知道觀察它的物件,並且當狀態發生變化的時候,需要能夠與那些觀察者通訊。此外,觀察者應該被自動通知。 示例 設想我們需要一個系統來建模本地蔬菜市場中蔬菜價格的波動。 我們需要允許餐館檢視價格,並在特定蔬菜的價格低於指定閾

一看就懂【來自英雄聯盟蓋倫的怒吼】與 Python 詳解設計模式(二)觀察模式

觀察者模式概述 觀察者模式(有時又被稱為模型-檢視(View)模式、源-收聽者(Listener)模式或從屬者模式)是軟體設計模式的一種。在此種模式中,一個目標物件管理所有相依於它的觀察者物件,並且在它本身的狀態改變時主動發出通知。這通常透過呼叫各觀察者所提供的方法來實現。此種模式通常被用來實現事件處理系統

設計模式之禪(2)-觀察模式

文章目錄 一、什麼是觀察者模式 二、通過設計氣象站模組來說明觀察者模式 2.1、觀察者模式設計的一般類圖 2.2、觀察者模式帶來的鬆耦合 2.3、氣象站模組需求 2.4、使用

PHP設計模式(5)—— 觀察模式

基本概念 整個觀察者模式,其實做的就是監聽事件、處理事件。 由此引出兩個角色,一個是觀察者Listener,另一個是事件處理者Handler。 例子 第一步,建立抽象事件類。 它的主要作用是提供兩個方法給具體事件類呼叫。 abstract clas

設計模式(四)觀察模式

繼續設計模式的文章,今天給大家帶來觀察者模式。先來看看觀察者模式的定義:定義了物件之間的一對多的依賴,這樣一來,當一個物件改變時,它的所有的依賴者都會收到通知並自動更新。好了,對於定義的理解總是需要例項來解析的,如今的微信服務號相當火啊,下面就以微信服務號為背景,給大家介紹

單例模式

一、單例模式     1、餓漢式 /** * 餓漢式單例模式 */ public class Singleton implements Serializable{ //餓漢式 直接建立 private static Singleton singleto

設計模式學習筆記】觀察模式

觀察者模式,提供了一種實時監聽方案。定義物件間的一種一對多的依賴關係,當一個物件的狀態發生改變時,所有依賴於它的物件都得到通知並被自動更新。[菜鳥] 文章目錄 1.1 被觀察者 1.2 觀察者 1.3 測試 1.4

Head First設計模式 第二章:觀察模式

觀察者模式是JDK中使用最多的模式之一。 氣象監測應用: 任務: WeatherData物件負責追蹤目前的天氣狀況(溫度、溼度、氣壓)。建立一個應用,有三種佈告板,分別顯示目前的狀況、氣象統計及簡單的預報。當WeatherObject 物件獲得最新的測量資料時, 三種佈

Java設計模式學習筆記(觀察模式

觀察者模式說起來很簡單,就是一個訂報紙的模式。但是實際上這部分我覺得還是很有意思的,《Head First設計模式》裡還有一些還沒看完,也是因為理解的不夠深吧。     觀察者模式會包含兩個元件:觀察者和主題。     這段程式碼是主題的介面: package

Java設計模式(4)--觀察模式

今天看了一下觀察者模式,總體來說不難,關鍵是要知道原理和這個模式的用法下面是我自己個人一些理解。 1、定義 觀察者模式,首先得有觀察者,一個或者多個觀察者,它們都依賴於另一個物件,也就是說,這些觀察者都觀察著一個被觀察者。那麼,當被觀察者狀態發生改變

Cocos2d-x設計模式之六 :觀察模式

1、應用場景 前面在介紹單例模式的時候,提到了一個類CCNotificationCenter,它除了應用單例模式以外,還應用了觀察者模式。CCNotificationCenter類是觀察者模式中的目標物件,而CCNotificationObserver則是觀察者。 一個目標物件可以註冊多個觀察者,當目標物件

java設計模式十五(觀察模式

java設計模式—觀察者模式 一.概述 在物件之間定義了一對多的依賴,這樣一來,當一個物件改變狀態,依賴它的物件會收到通知並自動更新。這有點像我們的maven,比如maven的pom.xml刪除某個依賴包時,eclipse裡的程式碼就會做出相應的錯誤提示