用boost::signal实现Observer模式

在没有掌握boost::signal之前,要用C++语言自己实现Observer模式真是一场对我耐心的考验。我首先要建立一个抽象基类Observer并为它声明N个纯虚接口,然后让这个家伙做我程序中所有ConcreteObserver类的爹,如果已经有爹的就再认一个,从而打开多重继承的潘多拉……正在我皱眉的时候,编译器告诉我:别慌,烦恼才刚刚开始呢微笑别废话,先让Observer的每个儿子把它的纯虚接口都给实现了,没用就弄个空壳子。现在可以决定怎么用这些傻了吧叽的Observer了:先在Subject类中定义N个队列(当然也可以只定义一个,代价是即使Observer们都是瞎子——空壳子也都要眼巴巴地“观察”),里面放指向抽象的指针,使用的时候需要小心指针的维护成本,智能指针可以安全高效的运行,但如果要在运行时管理这群Observer们的行为那就得自己费心了,用的时候保证在Observer队列中,不用的时候把它们拿走,从派生的概念讲它们还都是哥们兄弟,因此你要注意它们当中有没有还是父子关系的,以及新添加的小哥们的身份……

z Z Z Z Z、z Z ZZZ

有了boost::signal之后,问题大大简化,因为不必再给那些Observer们硬生生地找个爹了,关系乱了真是麻烦啊。

最后放出boost库示例的修改版,以便日后照葫芦画瓢。

#include <iostream>
#include <string>
#include <boost/signal.hpp>
#include <boost/bind.hpp>

class Subject
{
public:
        typedefboost::signal<void(bool)>  signal_t;
        typedefboost::signals::connection connection_t;

public:
        Subject()
       {}

        // 安装一个回调处理
        connection_tconnect(signal_t::slot_function_typesubscriber)
        {
               return m_sig.connect(subscriber);
        }

        // 断开回调处理
        voiddisconnect(connection_t subscriber)
        {
               subscriber.disconnect();
        }

        void append(constchar* s)
        {
               m_text += s;

               // 通知Observer们,本例只有一个
               m_sig(true);
        }

        conststd::string&getText() const
        {
               return m_text;
        }

private:
       signal_t    m_sig;
       std::string m_text;
};

class Observer
{
public:
        Observer(Subject& m)
               : m_Subject( m)
        {
               m_connection = m_Subject.connect(boost::bind(&Observer::refresh,this, _1) );
        }

        virtual~Observer()
        {
               m_Subject.disconnect( m_connection);
        }

        //Subject发布消息后Observer的内部处理入口
        virtual void refresh(bool bExtended) const = 0;

protected:
       Subject&              m_Subject;

private:
       Subject::connection_t m_connection;
};

class SubObserver : public Observer
{
public:
        SubObserver(Subject& doc)
               : Observer( doc)
       {}

        //重载Subject发布消息后Observer的内部处理入口
        virtual void refresh(bool bExtended) const
        {
               std::cout<< "TextView: "<< m_Subject.getText()<<std::endl;
        }
};

int main( int argc, char* argv[])
{
        Subject doc;
        SubObserver v1(doc);

        doc.append( argc == 2? argv[ 1] : "Hello world!");
        return 0;
}
我奇怪boost的设计者们的脑袋是怎么长的,用程序实现出来设计模式,我对他们佩服极了。现在我觉得自己对C++的认识也就算是个入门级的,掌握了boost、loki等库的用法才算是个熟练的技术工人,看懂boost的源代码才算真正领悟C++的精髓,有能力扩充boost或编写通用C++组件来解决实际问题才能算精通,也许几年、十几年、几十年,甚至我一生都达不到那样的高度,真是条艰险的前进之路啊。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值