• 小话设计模式三:发布/订阅模式


    发布/订阅模式定义:

      又称为观察者模式,定义对象间的一种一对多的依赖关系,一个发布者可以对应多个订阅者,当发布者发生变化的时候,他可以将消息一一通知给所有的订阅者当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

    发布/订阅模式解析:

      UML图如下,这里发布者IPublisher提供依赖于它的订阅者的添加add和删除remove操作,同时提供一个依赖于它的所有订阅者同步的操作notify。订阅者需要提供一个update操作,当发布者发出notify通知所有订阅者时,进行调用update。                           

      简单代码示例如下:

    //订阅者基类
    class ISubscriber
    {
    public:
        ISubscriber(string name);
        virtual void update(string strMsg) = 0;  //更新订阅者自身状态,由发布者调用
        virtual ~ISubscriber(){};
    protected:
        string m_name;    //订阅者名称
    };
    
    ISubscriber::ISubscriber(string name) : m_name(name)
    {
    }
    
    //发布者基类
    class IPublisher
    {
    public:
        virtual void add(ISubscriber *pObserver) = 0;    //增加订阅者
        virtual void remove(ISubscriber *pObserver) = 0; //移除订阅者
        virtual void notify() = 0;                       //通知订阅者
        virtual ~IPublisher(){};
        void setMsg(string strMsg);
        string getMsg();
    protected:
        std::list<ISubscriber*> m_listObserver;          //保存所有订阅者的列表
        string m_strMsg;                                 //发布者发布的消息
    };
    
    void IPublisher::setMsg(string strMsg)
    {
        m_strMsg = strMsg;
    }
    
    string IPublisher::getMsg()
    {
        return m_strMsg;
    }
    
    //发布者的实现类
    class PublisherImpl : public IPublisher
    {
    public:
        virtual void add(ISubscriber *pObserver);
        virtual void remove(ISubscriber *pObserver);
        virtual void notify();
        ~PublisherImpl();
    
    };
    
    void PublisherImpl::add(ISubscriber *pObserver)
    {
        std::list<ISubscriber*>::iterator iter = find(m_listObserver.begin(), m_listObserver.end(), pObserver);
        if (iter == m_listObserver.end())
        {
            m_listObserver.push_back(pObserver);
        }
    }
    
    void PublisherImpl::remove(ISubscriber *pObserver)
    {
        std::list<ISubscriber*>::iterator iter = find(m_listObserver.begin(), m_listObserver.end(), pObserver);
        if (iter != m_listObserver.end())
        {
            m_listObserver.erase(iter);
        }
    }
    
    void PublisherImpl::notify()
    {
        std::list<ISubscriber*>::iterator iter;
        for (iter = m_listObserver.begin(); iter != m_listObserver.end(); ++iter)
        {
            (*iter)->update(m_strMsg);
        }
    }
    
    PublisherImpl::~PublisherImpl()
    {
        std::list<ISubscriber*>::iterator iter, temp;
        for (iter = m_listObserver.begin(); iter != m_listObserver.end(); ++iter)
        {
            temp = iter;
            delete (*temp);
        }
        m_listObserver.clear();
    }
    
    //订阅者的实现类一
    class CSDNSubscriber : public ISubscriber
    {
    public:
        CSDNSubscriber(string name);
        virtual void update(string strMsg);
    };
    
    CSDNSubscriber::CSDNSubscriber(string name) : ISubscriber(name)
    {
    }
    
    void CSDNSubscriber::update(string strMsg)
    {
        cout<<strMsg<<", 请关闭CSDN,停止上网,开始认真工作!"<<endl;
    }
    
    //订阅者的实现类二
    class ChatSubscriber : public ISubscriber
    {
    public:
        ChatSubscriber(string name);
        virtual void update(string strMsg);
    };
    
    ChatSubscriber::ChatSubscriber(string name) : ISubscriber(name)
    {
    }
    
    void ChatSubscriber::update(string strMsg)
    {
        cout<<strMsg<<", 请停止聊天,开始认真工作!"<<endl;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        IPublisher *pSubject = new PublisherImpl;
        ISubscriber *pSubscriber = NULL;
        pSubscriber = new CSDNSubscriber("张三");  //向发布者中注册订阅者
        pSubject->add(pSubscriber);
        pSubscriber = new ChatSubscriber("李四");
        pSubject->add(pSubscriber);
        pSubscriber = new ChatSubscriber("王五");
        pSubject->add(pSubscriber);
        pSubject->setMsg("主管回来了");
        pSubject->notify();                    //发布者通知所有订阅者
    return 0; }
  • 相关阅读:
    modals-methods 模态框 使用说明文档
    jquery validate form 异步提交
    log在线生成器 html中如何设置浏览器中标题前的logo
    解决django关于图片无法显示的问题
    Git远程操作
    Git基本操作
    Git思维导图
    连接GitHub的方法
    Git的三种区域
    Gentoo(贱兔)Linux安装笔记
  • 原文地址:https://www.cnblogs.com/venow/p/2752229.html
Copyright © 2020-2023  润新知