接口优化了的观察者模式

来源:互联网 发布:软件流程图模板 编辑:程序博客网 时间:2024/05/21 06:46

接口优化了的观察者模式

之前在写基于MFC实现图表绘制软件的时候, 封装了一个优化接口的观察者模式。不用统一接口也能使用,代码简单清晰。我觉得很有用处,因此在这里分享出来。

1. 实现的效果

优化了接口过后的观察者模式,可以实现让继承自 Subject 的类对普通类进行通知的功能,可以动态的绑定和卸载绑定的响应函数。

  • 实现接口
    a. 将普通类 TypNonObs 对象的 pf 函数关联到通知对象 ps
template<typename Ty>bool Bind(Subject* ps, Ty* pNonObs,    typename Subject::NonObserverRef<Ty>::FuncUpdateRef pf);

b. 将普通类 TypNonObs 对象的到 pf 函数与通知对象 ps 解绑。

template<typename Ty>bool UnBind(Subject* ps, Ty* pNonObs,     typename Subject::NonObserverRef<Ty>::FuncUpdateRef pf = nullptr);
  • 测试效果
    a. 样例代码:
#include <iostream>#include "Subject.h"using namespace std;using namespace yl;class NonObserver{public:    void Show()    {        cout << "NonObserver Show..." << endl;    }    void Show1()    {        cout << "NonObserver Show1..." << endl;    }};class NonObserver1{public:    void Show()    {        cout << "NonObserver1 Show..." << endl;    }    void Show1()    {        cout << "NonObserver1 Show1..." << endl;    }};//MySubject 继承自Subjectclass MySubject : public Subject{    // Do anything you want...};int main(){    MySubject ms;    NonObserver no;    NonObserver non;    NonObserver1 no1;    NonObserver1 non1;    //绑定    Bind(&ms, &no, &NonObserver::Show);    Bind(&ms, &no, &NonObserver::Show1);    Bind(&ms, &no1, &NonObserver1::Show);    Bind(&ms, &no1, &NonObserver1::Show1);    Bind(&ms, &non1, &NonObserver1::Show);    Bind(&ms, &non1, &NonObserver1::Show1);    Bind(&ms, &non, &NonObserver::Show);    Bind(&ms, &non, &NonObserver::Show1);    //发送通知    ms.Notify();    cout << endl;    cout << "解绑 ms 对象的所有响应函数..." << endl;    UnBind(&ms, &no);    //发送通知    ms.Notify();    cout << endl;    cout << "解绑 no1 对象的 NonObserver1::Show 响应函数..." << endl;    UnBind(&ms, &no1, &NonObserver1::Show);    //发送通知    ms.Notify();    cout << endl;    cout << "解绑NonObserver1类对象的 Show 响应函数..." << endl;    //注意, 如果这里直接用 nullptr 的话, 无法推断类型    UnBind(&ms, (NonObserver1*)nullptr, &NonObserver1::Show1);    //发送通知    ms.Notify();    cout << endl;    cout << "解绑所有对象的响应函数..." << endl;    UnBind(&ms);    //发送通知    ms.Notify();    return 0;}

b. 运行结果

NonObserver Show...NonObserver Show1...NonObserver1 Show...NonObserver1 Show1...NonObserver1 Show...NonObserver1 Show1...NonObserver Show...NonObserver Show1...解绑 ms 对象的所有响应函数...NonObserver1 Show...NonObserver1 Show1...NonObserver1 Show...NonObserver1 Show1...NonObserver Show...NonObserver Show1...解绑 no1 对象的 NonObserver1::Show 响应函数...NonObserver1 Show1...NonObserver1 Show...NonObserver1 Show1...NonObserver Show...NonObserver Show1...解绑NonObserver1类对象的 Show 响应函数...NonObserver1 Show...NonObserver Show...NonObserver Show1...解绑所有对象的响应函数...

2. 源代码

  • Subject.h 文件
/****************************************************************** Program Assignment :      接口优化了的观察者模式* Author:                   @杨领well(blog.csdn.net/yanglingwell)* Date:                     2017/03/15  19:22* Description:              利用模板和重载实现接口优化*****************************************************************/#pragma once#include <list>namespace yl{    class Subject    {    public:        //观察者的基类        class IObserver        {        public:            virtual void Update() = 0;            virtual bool operator==(const IObserver&) = 0;            virtual void clear() = 0;        protected:            ~IObserver() {}        };        //Subject存响应消息的类的辅助类(adapter)        template <typename Ty>        class NonObserverRef : public IObserver        {        public:            typedef Ty ObserverType;            typedef NonObserverRef<Ty> Type;            //响应消息的函数指针类型            typedef void (Ty::*FuncUpdateRef)();        public:            NonObserverRef(ObserverType* pNonObserver, FuncUpdateRef updateRef = nullptr)                : m_pNonObserver(pNonObserver), m_funcUpdateRef(updateRef) {}        public:            void Update() override            {                if (m_funcUpdateRef != nullptr)                {                    (m_pNonObserver->*m_funcUpdateRef)();                }            }            bool operator==(const IObserver& obs) override            {                const Type* dObs = dynamic_cast<const Type*>(&obs);                if (dObs == nullptr) return false;                if (dObs->m_pNonObserver == this->m_pNonObserver)                {                    if (dObs->m_funcUpdateRef == nullptr                        || m_funcUpdateRef == dObs->m_funcUpdateRef)                    {                        return true;                    }                    else                    {                        return false;                    }                }                else if (dObs->m_funcUpdateRef == m_funcUpdateRef                    && dObs->m_pNonObserver == nullptr)                {                    return true;                }                else                {                    return false;                }            }            void clear() override            {                delete this;            }        private:            ObserverType* m_pNonObserver;            FuncUpdateRef m_funcUpdateRef;        };    public:        virtual ~Subject();    public:        void Notify();        void Attach(IObserver* pObs)        {            m_obs.push_back(pObs);        }        void Detach(IObserver* pObs = nullptr);    private:        std::list<IObserver*> m_obs;    };    //绑定 pNonObs::pf 响应 ps 的通知    template<typename Ty>    bool Bind(Subject* ps, Ty* pNonObs,        typename Subject::NonObserverRef<Ty>::FuncUpdateRef pf)    {        if (ps == nullptr || pNonObs == nullptr || pf == nullptr)        {            return false;        }        ps->Attach(new typename Subject::NonObserverRef<Ty>(pNonObs, pf));        return true;    }    //解绑 pNonObs::pf 响应 ps 的通知, 如果 pf==nullptr, 则解绑PNodObs的所有响应函数    template<typename Ty>    bool UnBind(Subject* ps, Ty* pNonObs,         typename Subject::NonObserverRef<Ty>::FuncUpdateRef pf = nullptr)    {        if (ps == nullptr && pNonObs == nullptr)        {            return false;        }        ps->Detach(new typename Subject::NonObserverRef<Ty>(pNonObs, pf));        return true;    }    extern bool UnBind(Subject* ps = nullptr);}

b. Subject.cpp 的源码

/****************************************************************** Program Assignment :      接口优化了的观察者模式* Author:                   @杨领well(blog.csdn.net/yanglingwell)* Date:                     2017/03/15  19:22* Description:              利用模板和重载实现接口优化*****************************************************************/#include "Subject.h"using namespace yl;yl::Subject::~Subject(){    Detach();}void yl::Subject::Notify(){    std::list<IObserver*>::iterator iter = m_obs.begin();    while (iter != m_obs.end())    {        (*iter++)->Update();    }}void yl::Subject::Detach(IObserver* pObs /*= nullptr*/){    std::list<IObserver*>::iterator iter = m_obs.begin();    while (iter != m_obs.end())    {        if (pObs == nullptr || **iter == *pObs)        {            (*iter)->clear();            iter = m_obs.erase(iter);        }        else        {            ++iter;        }    }    if(pObs) pObs->clear();}bool yl::UnBind(Subject* ps /*= nullptr*/){    if (ps == nullptr) return false;    ps->Detach();    return true;}

3. 源码下载

github.com

1 0
原创粉丝点击