C++设计模式——观察者模式

观察者模式(Observer)

        观察者模式是目前应用最广、影响范围最大的模式之一,因为 Observer 的一个实例Model/View/Control( MVC) 结构在系统开发架构设计中有着很重要的地位和意义, MVC实现了业务逻辑和表示层的解耦。个人也认为 Observer 模式是软件开发过程中必须要掌握和使用的模式之一。在 MFC 中, Doc/View(文档视图结构)提供了实现 MVC 的框架结构。同样Qt中核心机制:信号和槽的实现也同样有观察者的影子。

        Observer 模式要解决的问题为: 建立一个一( Subject)对多( Observer) 的依赖关系, 并且做到当“一” 变化的时候, 依赖这个“一”的多也能够同步改变。Observer 模式也称为发布-订阅( publish-subscribe),目标就是通知的发布者,观察者则是通知的订阅者(接受通知)。 最常见的一个例子就是: 对同一组数据进行统计分析时候, 我们希望能够提供多种形式的表示(例如以表格进行统计显示、 柱状图统计显示、 百分比统计显示等)。这些表示都依赖于同一组数据, 我们当然需要当数据改变的时候, 所有的统计的显示都能够同时改变。Observer 模式就是解决了这一个问题。Observer模式提供给关联对象一种同步通信的手段,使某个对象与依赖它的其他对象之间保持状态同步。

观察者(Observer)模式典型的结构图如下:

C++设计模式——观察者模式

        这里的目标 Subject 提供依赖于它的观察者 Observer 的注册( Attach) 和注销( Detach)操作,并且提供了使得依赖于它的所有观察者同步的操作( Notify)。 观察者 Observer 则提供一个 Update 操作, 注意这里的 Observer 的 Update 操作并不在 Observer 改变了 Subject 目标状态的时候就对自己进行更新, 这个更新操作要延迟到 Subject 对象发出 Notify 通知所有Observer 进行修改(调用 Update)。

观察者模式结构

C++设计模式——观察者模式

Subject(被观察者)

 被观察的对象。当需要被观察的状态发生变化时,需要通知队列中所有观察者对象。Subject需要维持(添加,删除,通知)一个观察者对象的队列列表。

ConcreteSubject

被观察者的具体实现。包含一些基本的属性状态及其他操作。

Observer(观察者)

接口或抽象类。当Subject的状态发生变化时,Observer对象将通过一个callback函数得到通知。

ConcreteObserver

观察者的具体实现。得到通知后将完成一些具体的业务逻辑处理。

观察者模式类封装

template <typename T>

class IObserver

{

        /* 更新观察者 */

        virtual void Update(const T &t) = 0;

        virtual ~IObserver(){}

};



template <typename T>

class CSubject

{

public:

        CSubject()

        {

        }



        CSubject(const CSubject<T>& oValue)

        {

                m_oObserverList = oValue.m_oObserverList;

        }



        virtual ~CSubject()

        {

                Clear();

        }



        /* 注册观察者 */

        qint32 Attach(IObserver<T> *pObserver)

        {

                if (NULL == pObserver)

                {

                        return COMMON_INVALIDPARAM;

                }



                typename std::list<IObserver<T> *>iterator it = std::find(m_oObserverList.begin(),                 m_oObserverList.end(), pObserver);



                if (it != m_oObserverList.end())

                {

                        return COMMON_ALREADY_EXIST;

                }

                m_oObserverList.push_back(pObserver);

                return COMMON_SUCCEED;

        }



        /* 注销观察者 */

        void Detatch(IObserver<T> *pObserver)

        {

                if (NULL == pObserver)

                {

                        return COMMON_INVALIDPARAM;

                }



                typename std::list<IObserver<T> *>iterator it = std::find(m_oObserverList.begin(),                 m_oObserverList.end(), pObserver);

                if (m_oObserverList.end() == it)

                {

                        return COMMON_NOTFOUND;

                }

                m_oObserverList.erase(it);

                return COMMON_SUCCEED;

        }



        /* 目标状态发生变化时,通知所有的观察者 */

        void Notify(const T &t)

        {

                typedef std::list<IObserver<T> *>::iterator it = m_oObserverList.begin();

                for (; it != m_oObserverList.end(); ++it)

                {

                        (*it)->Update(t);

                }

        }



        /* 从清空所有观察者 */

        void Clear()

        {

                m_oObserverList.clear();

        }

private:

        std::list<IObserver<T> *> m_oObserverList; /* 保存观察者的链表对象 */

};

应用场景

  • 侦听事件驱动程序设计中的外部事件
  • 侦听/监视某个对象的状态变化
  • 发布者/订阅者(publisher/subscriber)模型中,当一个外部事件(新的产品,消息的出现等等)被触发时,通知邮件列表中的订阅者

        适用于: 定义对象间一种一对多的依赖关系,使得每一个对象改变状态,则所有依赖于他们的对象都会得到通知。 使用场景:定义了一种一对多的关系,让多个观察对象(公司员工)同时监听一个主题对象(秘书),主题对象状态发生变化时,会通知所有的观察者,使它们能够更新自己。

应用实例

#include <iostream>

using namespace std;

#include "vector"

#include "string"



class Secretary;



//玩游戏的同事类(观察者)

class PlayserObserver

{

public:

PlayserObserver(string name, Secretary *secretary)

{

m_name = name;

m_secretary = secretary;

}

void update(string action)

{

cout << "观察者收到action:" << action << endl;

}

private:

string m_name;

Secretary *m_secretary;

};



//秘书类(主题对象,通知者)

class Secretary

{

public:

void addObserver(PlayserObserver *o)

{

     v.push_back(o);

}

void Notify(string action)

{

     for (vector<PlayserObserver *>::iterator it= v.begin(); it!=v.end(); it++ )

{

(*it)->update(action);

}

}

void setAction(string action)

{

m_action = action;

Notify(m_action);

}

private:

string m_action;

vector<PlayserObserver *> v;

};



void main()

{

//subject 被观察者

Secretary *s1 = new Secretary;



//具体的观察者 被通知对象

PlayserObserver *po1 = new PlayserObserver("小张", s1);

//PlayserObserver *po2 = new PlayserObserver("小李", s1);

s1->addObserver(po1);

//s1->addObserver(po2);

s1->setAction("老板来了");

s1->setAction("老板走了");

cout<<"hello..."<<endl;

system("pause");

return ;

}

上一篇:vlan实例配置web版(转)


下一篇:局域网组网 | 交换机常用命令