Observer(观察者)-对象行为型模式

1.意图

    定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

2.别名

    依赖(Depenents),发布-订阅(Publish-subscribe)

3.动机

    一个目标可以有任意数目的依赖它的观察者。一旦目标的状态发生改变,所有的观察者都得到通知。作为这个通知的响应,每个观察者都将查询目标以使其状态于目标的同步。

4.适用性

  • 当一个抽象模型有两个方面,其中一个方面依赖于另一个方面。将这二者封装在独立的对象中以使它们可以各自独立改变和复用。
  • 当一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变。
  • 当一个对象必须通知其它对象,而它又不能假定其它对象是谁。换言之,你不希望这些对象是紧耦合的。

5.结构

    

6.代码实例

//Subject.h

#include <memory>
#include <vector>

class AbstractObserver;

class AbstractSubject
{
public:
    virtual void Attach(std::shared_ptr<AbstractObserver> pObserber)=0;
    virtual void Notify()=0;
    virtual void SetState(int state)=0;
    virtual int GetState()=0;
};

class ConcreteSubject : public AbstractSubject
{
public:
    ConcreteSubject();
    ~ConcreteSubject();
    virtual void Attach(std::shared_ptr<AbstractObserver> pObserber);
    virtual void Notify();
    virtual void SetState(int state);
    virtual int GetState();
private:
    std::vector<std::shared_ptr<AbstractObserver>> m_vecObservers;
    int m_state;
};
//Observer.h

#include <memory>

class AbstractSubject;

class AbstractObserver
{
public:
    virtual void Update()=0;
};

class ConcreteObserver1 : public AbstractObserver
{
public:
    ConcreteObserver1(std::shared_ptr<AbstractSubject> pSubject);
    ~ConcreteObserver1();
    virtual void Update();
private:
    std::shared_ptr<AbstractSubject> m_Subject;
};

class ConcreteObserver2: public AbstractObserver
{
public:
    ConcreteObserver2(std::shared_ptr<AbstractSubject> pSubject);
    ~ConcreteObserver2();
    virtual void Update();
private:
    std::shared_ptr<AbstractSubject> m_Subject;
};

class ConcreteObserver3 : public AbstractObserver
{
public:
    ConcreteObserver3(std::shared_ptr<AbstractSubject> pSubject);
    ~ConcreteObserver3();
    virtual void Update();
private:
    std::shared_ptr<AbstractSubject> m_Subject;
};
//Subject.cpp

#include "Subject.h"
#include "Observer.h"

ConcreteSubject::ConcreteSubject()
{
}

ConcreteSubject::~ConcreteSubject()
{
}

void ConcreteSubject::SetState(int state)
{
    m_state = state;
}

void ConcreteSubject::Attach(std::shared_ptr<AbstractObserver> pObserver)
{
    m_vecObservers.push_back(pObserver);
}

int ConcreteSubject::GetState()
{
    return m_state;
}

void ConcreteSubject::Notify()
{
    for(auto iter = m_vecObservers.begin(); iter != m_vecObservers.end(); ++iter)
    {
        (*iter)->Update();
    }
}
// Observer.cpp


#include "Observer.h"
#include "Subject.h"
#include <iostream>

ConcreteObserver1::ConcreteObserver1(std::shared_ptr<AbstractSubject> pSubject)
    : m_Subject(pSubject)
{
}

ConcreteObserver1::~ConcreteObserver1()
{
}

void ConcreteObserver1::Update()
{
    std::cout << "ConcreteObserver1 Updated state:" << m_Subject->GetState() << std::endl;
}


ConcreteObserver2::ConcreteObserver2(std::shared_ptr<AbstractSubject> pSubject)
    : m_Subject(pSubject)
{
}

ConcreteObserver2::~ConcreteObserver2()
{
}

void ConcreteObserver2::Update()
{
    std::cout << "ConcreteObserver2 Updated state:" << m_Subject->GetState() << std::endl;
}


ConcreteObserver3::ConcreteObserver3(std::shared_ptr<AbstractSubject> pSubject)
    : m_Subject(pSubject)
{
}

ConcreteObserver3::~ConcreteObserver3()
{
}

void ConcreteObserver3::Update()
{
    std::cout << "ConcreteObserver3 Updated state:" << m_Subject->GetState() << std::endl;
}
//client.cpp

#include "Observer.h"
#include "Subject.h"


int main()
{
    std::shared_ptr<AbstractSubject> pSubject(new ConcreteSubject);
    
    std::shared_ptr<AbstractObserver> pObserver1(new ConcreteObserver1(pSubject));
    std::shared_ptr<AbstractObserver> pObserver2(new ConcreteObserver2(pSubject));
    std::shared_ptr<AbstractObserver> pObserver3(new ConcreteObserver3(pSubject));

    pSubject->Attach(pObserver1);
    pSubject->Attach(pObserver2);
    pSubject->Attach(pObserver3);

    pSubject->SetState(5);

    pSubject->Notify();

    while(1);
}

7.测试结果

    

8.效果

  • 目标和观察者间的抽象耦合
  • 支持广播通信
  • 意外的更新 因为一个观察者并不知道其它观察者的存在,它可能对改变目标的最终代价一无所知。在目标上一个看似无害的操作可能会引起一系列对观察者以及依赖于这些观察者的那些对象的更新。此外,如果依赖准则的定义或维护不当,常常会引起错误的更新,这种错误通常难以捕捉。
原文地址:https://www.cnblogs.com/mgp200866130/p/5723088.html