设计模式之 观察者模式(Publish/Subscribe)模式

介绍

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。 这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。[DP]

  • Subject被观察者
    定义被观察者必须实现的职责,它必须能够动态地增加、取消观察者。它一般是抽象类或者是实现类,仅仅完成作为被观察者必须实现的职责:管理观察者并通知观察者。
  • Observer观察者
    观察者接收到消息后,即进行update(更新方法)操作,对接收到的信息进行处理。
  • ConcreteSubject具体的被观察者
    定义被观察者自己的业务逻辑,同时定义对哪些事件进行通知。
  • ConcreteObserver具体的观察者
    每个观察在接收到消息后的处理反应是不同,各个观察者有自己的处理逻辑。

优点:观察者和被观察者之间是抽象耦合;建立一套触发机制

应用:关联行为场景。需要注意的是,关联行为是可拆分的,而不是组合关系;事件多级触发场景;跨系统的消息交换场景,如消息队列的处理机制

注意:广播连,消息最多转发一次(传递两次)

 

UML类图

简单示例代码:

#ifndef SIMPLE_OBSERVER_H
#define SIMPLE_OBSERVER_H

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

using namespace std;

/**
 * @brief The Observer class
 * 抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。
 * 抽象观察者一般用一个抽象类或者一个接口实现,通常包含一个Update()方法
 */
class Observer
{
public:
    virtual void update()
    {
        cout<<"Observer::update()"<<endl;
    }
};

/**
 * @brief The Subject class
 * 抽象通知者,它把所有对观察者对象的引用保存在一个聚集里
 */
class Subject
{
public:
    void attach(Observer *ob)
    {
        m_observers.push_back(ob);
    }

    void detach(Observer *ob)
    {
        m_observers.remove(ob);
    }

    void notify()
    {
        for (list<Observer *>::iterator it = m_observers.begin(); it != m_observers.end() ;it++) {
            (*it)->update();
        }
    }

private:
    list<Observer *> m_observers;
};

/**
 * @brief The ConcreteSubject class
 * 具体通知者
 */
class ConcreteSubject : public Subject
{
public:
    //具体被观察者的状态
    string getSubjectState()
    {
        return m_subjectState;
    }
    void setSubjectState(string stateStr)
    {
        m_subjectState = stateStr;
    }

private:
    string m_subjectState;
};

/**
 * @brief The ConcreteObserver class
 * 具体观察者
 */
class ConcreteObserver : public Observer
{
public:
    ConcreteObserver(ConcreteSubject *subject , string name)
    {
        m_subject = subject;
        m_name = name;
    }

    void update()
    {
        m_observerState = m_subject->getSubjectState();
        cout<<"观察者:"<<m_name<<"的状态是:"<<m_observerState<<endl;
    }


private:
    string m_name ;
    string m_observerState;
    ConcreteSubject *m_subject;
};


#endif // SIMPLE_OBSERVER_H

调用代码:

    ConcreteSubject *s = new ConcreteSubject;
    s->attach(new ConcreteObserver(s , "X"));
    s->attach(new ConcreteObserver(s , "Y"));
    s->attach(new ConcreteObserver(s , "Z"));

    s->setSubjectState("ABC");

    s->notify();

    s->setSubjectState("BCD");

    s->notify();

    delete  s;
    s = nullptr;

《大话设计模式种,公司前台场景代码》

#ifndef COMPANY_OBSERVER_H
#define COMPANY_OBSERVER_H

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

using namespace std;

class Subject;
/**
 * @brief The Observer class
 * 抽象观察者,为所有的具体观察者定义一个接口,在得到主题的通知时更新自己。
 * 抽象观察者一般用一个抽象类或者一个接口实现,通常包含一个Update()方法.
 *
 * 创建该观察者同时,提供一个抽象通知者,因为此时通知者有可能会变。
 */
class Observer
{
public:

    Observer(Subject *sub , string name)
    {
        m_subject = sub;
        m_name = name;
    }
    virtual void update()
    {
        cout<<"Observer::update()"<<endl;
    }

protected:
    string m_name ;
    Subject *m_subject;
};


/**
 * @brief The Subject class
 * 抽象通知者,它把所有对观察者对象的引用保存在一个聚集里
 * 因为此时的通知者不知是:前台  还是   老板
 */
class Subject
{
public:
    void virtual attach(Observer *ob) = 0;
    void virtual detach(Observer *ob) = 0;
    void virtual  notify() = 0;
    void virtual setAction(string act) = 0;
    string virtual getAction() const = 0;

};

/***********************************具体的通知者*****************************************/

/**
 * @brief The Boss class
 * 具体的通知者:老板自己回来了,前台美女不在
 */
class Boss : public Subject
{
public:
    void attach(Observer *ob)
    {
        m_observers.push_back(ob);
    }

    void detach(Observer *ob)
    {
        m_observers.remove(ob);
    }

    void notify()
    {
        for (list<Observer *>::iterator it = m_observers.begin(); it != m_observers.end() ;it++) {
            (*it)->update();
        }
    }

    void setAction(string act)
    {
        m_action = act;
    }

    string getAction() const
    {
        return m_action;
    }

private:
    list<Observer *> m_observers;
    string m_action;
};

/**
 * @brief The Secretary class
 * 具体的通知者:老板回来了,前台美女在
 */
class Secretary : public Subject
{
public:
    void attach(Observer *ob)
    {
        m_observers.push_back(ob);
    }

    void detach(Observer *ob)
    {
        m_observers.remove(ob);
    }

    void notify()
    {
        for (list<Observer *>::iterator it = m_observers.begin(); it != m_observers.end() ;it++) {
            (*it)->update();
        }
    }

    void setAction(string act)
    {
        m_action = act;
    }

    string getAction() const
    {
        return m_action;
    }

private:
    list<Observer *> m_observers;
    string m_action;
};


/***********************************具体的观察者******************************************/

/**
 * @brief The StockObserver class
 * 具体的观察者:看股票的同事
 */
class StockObserver : public Observer
{
public:
    StockObserver(Subject *sub , string name )
        :Observer(sub , name)
    {

    }

    void update() override
    {
        cout<<m_subject->getAction()<<"   "<<m_name<<"  关闭股票软件,继续工作。\n";
    }
};

/**
 * @brief The GameObserver class
 * 具体的观察者:玩游戏的同事
 */
class GameObserver : public Observer
{
public:
    GameObserver(Subject *sub , string name )
        :Observer(sub , name)
    {

    }

    void update() override
    {
        cout<<m_subject->getAction()<<"   "<<m_name<<"  停止玩游戏,继续工作。\n";
    }
};

/**
 * @brief The NBAObserver class
 * 具体的观察者:看NBA的同事
 */
class NBAObserver : public Observer
{
public:
    NBAObserver(Subject *sub , string name )
        :Observer(sub , name)
    {

    }

    void update() override
    {
        cout<<m_subject->getAction()<<"   "<<m_name<<"  停止观看NBA,继续工作。\n";
    }
};



#endif // COMPANY_OBSERVER_H

调用代码:

    /*
    //具体的通知者
    Boss *pHuhansan = new Boss;

    //老板回来,前台不在

    //看股票的同事
    StockObserver *pSo = new StockObserver( pHuhansan , "易小天");

    //看NBA的同事
    NBAObserver *pNo = new NBAObserver(pHuhansan , "赵高");

    //玩游戏的同事
    GameObserver *pGo = new GameObserver(pHuhansan , "项羽");

    //老板添加观察者
    pHuhansan->attach(pSo);
    pHuhansan->attach(pNo);
    pHuhansan->attach(pGo);

    pHuhansan->setAction("胡汉三我回来了");

    pHuhansan->notify();
    */

    //老板回来,前台在
    Secretary *pMeimei = new  Secretary;

    //看股票的同事
    StockObserver *pSo = new StockObserver( pMeimei , "易小天");

    //看NBA的同事
    NBAObserver *pNo = new NBAObserver(pMeimei , "赵高");

    //玩游戏的同事
    GameObserver *pGo = new GameObserver(pMeimei , "项羽");

    //前台添加观察者,关系不好的不让加
    pMeimei->attach(pSo);
    pMeimei->attach(pNo);
    pMeimei->attach(pGo);

    pMeimei->setAction("胡汉三大佬回来啦啦啦~~~");

    pMeimei->notify();

 

随着对该模式理解的深入,会随时更新该篇博客。

 

部分内容摘自网络,若有侵权,联系删除。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章