觀察者模式

1.動機

  • 創建一種對象與對象之間的依賴關係,一個對象發生改變時將自動通知其餘對象,其餘對象將相應作出反應。在此,發生改變的對象稱爲觀察目標,而被通知的對象稱爲觀察者,一個觀察目標能夠對應多個觀察者,並且這些觀察者之間沒有相互聯繫,能夠根據須要增長和刪除觀察者,使得系統更易於擴展。

2.定義

  • 觀察者模式(Observer Pattern):定義對象間的一種一對多的依賴關係當一個對象的狀態發生改變時,全部依賴於它的對象都獲得通知並被自動更新。當一個對象發生了變化,關注它的對象就會獲得通知;這種交互也稱爲發佈-訂閱(publish-subscribe)。目標是通知的發佈者,它發出通知時並不須要知道誰是它的觀察者。
  • 無論是折線圖、餅狀圖,仍是柱狀圖,它們都依賴於數據;當數據發生變化時,數據對象會通知依賴於它的對象去更新;因此就有了Excel中,當數據發生變化時,對應的統計圖也會自動的重繪。

3.結構

clipboard.png

Subject(目標)ios

  • 目標知道它的觀察者。能夠有任意多個觀察者觀察同一個目標;
  • 提供註冊和刪除觀察者對象的接口。

Observer(觀察者)spa

  • 爲那些在目標發生改變時需得到通知的對象定義一個更新接口。

ConcreteSubject(具體目標)code

  • 將有關狀態存入各ConcreteObserver對象;
  • 當它的狀態發生改變時,向它的各個觀察者發出通知。

ConcreteObserver(具體觀察者)server

  • 維護一個指向ConcreteSubject對象的引用;
  • 存儲有關狀態,這些狀態應與目標的狀態保持一致;
  • 實現Observer的更新接口以使自身狀態與目標的狀態保持一致。

觀察者模式按照如下方式進行協做:對象

  • 當ConcreteSubject發生任何可能致使其觀察者與其自己狀態不一致的改變時,它將通知它的各個觀察者;
  • 在獲得一個具體目標的改變通知後,ConcreteObserver對象可向目標對象查詢信息。ConcreteObserver使用這些信息以使它的狀態與目標對象的狀態一致。

clipboard.png

4.代碼分析

#include <iostream>
#include <list>
using namespace std;

class Observer
{
public:
    virtual void Update(int) = 0;
    virtual void showState() = 0;
};

class Subject
{
public:
    //添加某個觀察者
    virtual void Attach(Observer *) = 0;
    //刪除某個觀察者
    virtual void Detach(Observer *) = 0;
    virtual void Notify() = 0;
};

class ConcreteObserver : public Observer
{
public:
    ConcreteObserver(Subject *pSubject) : m_pSubject(pSubject){}

    //根據被觀察物的狀態更新本身的狀態
    void Update(int value)
    { 
        state = value;
    }

    void showState()
    {
        cout << "The State of ob:" << state << endl;
    }

private:
    Subject *m_pSubject;
    int state;
};

class ConcreteObserver2 : public Observer
{
public:
    ConcreteObserver2(Subject *pSubject) : m_pSubject(pSubject){}

    //根據被觀察物的狀態更新本身的狀態
    void Update(int value)
    {
        state = value;
    }

    void showState()
    {
        cout << "The State of ob2:"  << state << endl;
    }

private:
    //指向一個物體
    Subject *m_pSubject;
    int state;
};

class ConcreteSubject : public Subject
{
public:
    void Attach(Observer *pObserver);
    void Detach(Observer *pObserver);
    void Notify();

    void SetState(int state)
    {
        m_iState = state;
    }

private:
    //擁有的觀察者
    list<Observer *> m_ObserverList;
    //當前物體的狀態
    int m_iState;
};

void ConcreteSubject::Attach(Observer *pObserver)
{
    m_ObserverList.push_back(pObserver);
}

void ConcreteSubject::Detach(Observer *pObserver)
{
    m_ObserverList.remove(pObserver);
}

//更新全部觀察者的狀態
void ConcreteSubject::Notify()
{
    list<Observer *>::iterator it = m_ObserverList.begin();
    while (it != m_ObserverList.end())
    {
        (*it)->Update(m_iState);
        ++it;
    }
}

int main()
{
    // 建立一個實體
    ConcreteSubject *pSubject = new ConcreteSubject();

    // 建立所屬該實體的觀察者
    Observer *pObserver = new ConcreteObserver(pSubject);
    Observer *pObserver2 = new ConcreteObserver2(pSubject);

    // 設置物體狀態
    pSubject->SetState(2);

    // 註冊該物體的觀察者
    pSubject->Attach(pObserver);
    pSubject->Attach(pObserver2);
    
    //更新觀察者的狀態
    pSubject->Notify();
    pObserver->showState();
    pObserver2->showState();

    // 刪除觀察者
    pSubject->Detach(pObserver);

    //更新物體狀態
    pSubject->SetState(3);
    //更新觀察者狀態
    pSubject->Notify();
    pObserver->showState();
    pObserver2->showState();

    delete pObserver;
    delete pObserver2;
    delete pSubject;

    system("pause");
    return 0;
}

5.模式分析

  • 觀察者模式描述瞭如何創建對象與對象之間的依賴關係,如何構造知足這種需求的系統。
  • 這一模式中的關鍵對象是觀察目標和觀察者,一個目標能夠有任意數目的與之相依賴的觀察者,一旦目標的狀態發生改變,全部的觀察者都將獲得通知。
  • 做爲對這個通知的響應,每一個觀察者都將即時更新本身的狀態,以與目標狀態同步,這種交互也稱爲發佈-訂閱(publishsubscribe)。目標是通知的發佈者,它發出通知時並不須要知道誰是它的觀察者,能夠有任意數目的觀察者訂閱它並接收通知

6.優勢

  • 觀察者模式能夠實現表示層和數據邏輯層的分離,並定義了穩定的消息更新傳遞機制,抽象了更新接口,使得能夠有各類各樣不一樣的表示層做爲具體觀察者角色。
  • 觀察者模式在觀察目標和觀察者之間創建一個抽象的耦合
  • 觀察者模式支持廣播通訊
  • 觀察者模式符合「開閉原則」的要求。

7.缺點

  • 若是一個觀察目標對象有不少直接和間接的觀察者的話,將全部的觀察者都通知到會花費不少時間。
  • 若是在觀察者和觀察目標之間有循環依賴的話,觀察目標會觸發它們之間進行循環調用,可能致使系統崩潰。
  • 觀察者模式沒有相應的機制讓觀察者知道所觀察的目標對象是怎麼發生變化的,而僅僅只是知道觀察目標發生了變化。

8.適用環境

  • 一個抽象模型有兩個方面,其中一個方面依賴於另外一個方面。將這些方面封裝在獨立的對象中使它們能夠各自獨立地改變和複用。
  • 一個對象的改變將致使其餘一個或多個對象也發生改變,而不知道具體有多少對象將發生改變,能夠下降對象之間的耦合度。
  • 一個對象必須通知其餘對象,而並不知道這些對象是誰。
  • 須要在系統中建立一個觸發鏈,A對象的行爲將影響B對象,B對象的行爲將影響C對象……,可使用觀察者模式建立一種鏈式觸發機制。
相關文章
相關標籤/搜索