• 2010-09-13

    一个用C++实现的Dispatcher(三)

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://www.blogbus.com/dreamhead-logs/74916236.html

    eBen给《一个用C++实现的Dispatcher(二)》提出了一些非常好的问题,修正了一些细节。但有一点需要稍加讨论一下:
    那几个new,可能某些做服务器端程序的人会受不了. handlers倒是可以做成static的.所有对象共用一份就可以了.

    这个问题在实现这个dispatcher的时候,有人提出来过,但我依然坚持我的选择。

    似乎做过服务器应用的人对性能和内存都有着特别的敏感,我也做过,我也一样。如果每个请求都去创建dispatcher的话,不仅是内存,还有创建的成本在里面。

    但是,我们为什么要每次都去创建呢?如果一次创建好,就存放在内存中,不就没有这样的问题了。

    把handlers设计成static,不是一个好的设计,这样的话,这个dispatcher类本身就是有状态的了,一个对象的误操作很容易就影响到另外的对象。一个好的设计应该是尽可能无状态的,这也是全局变量不受欢迎的一个原因,杀伤力太大,且错误不好定位。

    之所以有人曾经给我提出过这个问题,因为他们的代码里有太多这样的代码:
    void Main::run() {
        ...
        MsgDispatcher dispatcher;
        dispatcher.dispatch(&msg);
        ...
    }

    这样的用法去使用这个dispatcher当然会有他们所担心的问题。解决起来很容易,把这个局部变量提取出来,比如做成类成员。

    我们现在知道了正确的做法是只初始化一次。不过,如果这是一个内层的代码就稍微麻烦一些了,即便这个类修正好了,我们不能保证这个代码在外层只调用了一次。面对遗留代码时,事往往不如意。

    在这种情况下,我会为这个dispatcher实现一个singleton:
    class MsgDispatcherSingleton {
    public:
        static MsgDispatcher* getDispatcher() {
            if (NULL == dispatcher) {
                dispatcher = new MsgDispatcher;
                …
            }

            return dispatcher;
        }
    private:
        MsgDispatcherSingleton() {}

        static MsgDispatcher* dispatcher;
    }

    MsgDispatcher* MsgDispatcherSingleton::dispatcher = NULL;

    需要知道的是,这是为了遗留代码所做的妥协,并不是我们真正设计的一部分。所以,我把它独立出来,如果有一天遗留代码被消除了,这个类也该随风而去。

    分享到:

    历史上的今天:

    引用地址: