现在的位置: 首页 > 综合 > 正文

libjingle中的signal/slot机制和观察者模式

2012年02月06日 ⁄ 综合 ⁄ 共 1517字 ⁄ 字号 评论关闭

什么是signal/slot机制?
    这是一种注册/回调机制,QT,libjingle中都很常用。它同时也是一种观察者模式的实现。

 

为什么需要signal/slot机制?
    表扬好同学之前,先批评下坏同学,就是MFC这个让很多IT童鞋头痛不已的框架。想象一个最常见的场景,拉一个对话框,上面放两个按钮,一个文本框,按钮按一下,文本框上数字增加或是减少一个。如果你来实现要怎么做呢?很简单么,SendMessage or PostMessage不就好了,那消息发给谁呢?爱谁谁么,直接发给文本框,要不统一发给对话框,让它转发不就行了么。无论是哪种方法都是糟糕的设计,难于扩展,难于维护,难于修改。为什么呢?先想想OO设计的第一原则,单一职责原则(SRP),每一个部件或是类都应该只负责一个功能,只有一个原因引起它的变化,可你看看可怜的按钮,它不就是一个框么,如果你按了它一下,它就简单的向外大喊一声,"我给打了",其他听到的同志就可以去救援了。关键在于按钮不应该维护(知道)自己需要把消息发给谁,也就是在OnClick函数中不应该有SendMessage(ligang,..)这样的代码,这会使得这个按钮完全失去可重用性,因为在别的场景中可没有这个ligang这个好同志。同样的如果我在对话框中加入另外一个图片框,按钮按下去的同时,这个图片框要换张图片,那就只能去按钮类的OnClick里去修改了,在加上几个SendMessage。这又违背了开闭原则,就算不去计较这些学究的原则,难道这样的代码不丑陋么?好的设计是怎样来实现这个场景的呢,其实也简单,按钮和文本框完全不需知道对方,按钮只管往外发消息,说明自己的状态,而不需要知道谁收到了消息,文本框受到了消息,相应的功能函数被调用,完全不需要知道谁调用了它,唯一需要知道两者联系的,并且建立,解除这种联系的是场景类,这里就是对话框。

    signal/slot机制很好的实现了上面的机制,这里介绍下libjingle中sigslot库的使用方法:

    class ButtonDec {
    public:
        signal0<> Click;
    }
    class ButtonInc {
    public:
        signal0<> Click;
    }

 

    class EditNum : public has_slot<>{
    public:
        void DecNumber();
        void IncNumber();
    }

    ButtonDec bt1;
    ButtonInc bt2;
    EditNum edit;
    bt1.Click.connect(edit, EditNum::DecNumber);
    bt1.Click.connect(edit, EditNum::IncNumber);
    //...do something
    bt1.Click.emit();
    bt2.Click.emit();

    多么清晰的设计啊,button类也好,Edit类也好,完全不需要知道对方,button只管emit就好了,相应的edit自然就会被做出update。
    关于sigslot库的详细使用这里不写了,具体的看http://sigslot.sourceforge.net/

 

什么是观察者模式?
    其实就是上面的signal/slot的抽象说法,回字的另一种写法是订阅发布模式,哎~哪里来的这么多名词啊。观察者模式的实现方法多种多样,各有适应的场景,目的都是一样的,在被观察者和观察者之间搭起一座沟通的桥梁,但是又让两者不过度耦合,便于维护,扩展。

抱歉!评论已关闭.