接口优化了的观察者模式

接口优化了的观察者模式

之前在写基于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 继承自Subject
class 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值