Modern C++ design 第六章

Singleton实作技术 

Singleton, 是一种描述非常简单, 应用和实现却很复杂的奇异模式, 有大量文献对Singleton做过讨论, “设计与模式”一书也用了很大的笔墨描述了Singleton的滥用所引发的问题, 并介绍了一些对Singleton的看法,以及去掉已存在的不合理Singleton的解决方法。 当然, 本书只是讨论Singleton的实现问题, 并不涉及模式的应用。

Singleton的实现方法, 唯一性, 生命期, 多线程是本书关注的重点。

首先: Singleton的最通用的实现方法, 就是用static函数instance来访问, 并有一个静态成员变量_singleton.  然后将构造,赋值都写成私有的。

摧毁Singleton的时候, 如果Singleton是用new分配的, 那么如果不显示的调用delete, 可能会内存泄露, 而如果用scott meyers的办法, 用静态成员变量,Singleton会自动在程序结束时候被析构。这里给了一个很有趣的东西, 就是在处理全局变量和静态变量的时候, 会通过调用atexit来注册destroy函数, 这个概念我是第一次见到:). 而后面的很多生命期管理,用到的都是这个咚咚了。

介绍了Dead Reference问题, 这是个复杂的问题,出现的很微妙,一般人可能根本不会去考虑(至少我是没有考虑过). Keyboard, Log, Display3个Singleton. 创立的顺序未知,而Keyboard和Display都会依赖Log. 问题出现了: keyboard构造成功,Display构造失败, Display产生一个Log错误,程序结束。按照Singleton的出现顺序。 首先, Keyboard构造, 然后Display, 然后Display析构,Log构造。 程序关闭,先析构Log, 最后析构Keyboard. (因为静态变量的析构是后生成先析构的). 但是如果Keyboard析构失败了, 需要调用Log来生成记录,那么Log此时已经被析构掉了,于是陷入一个不可知的陷阱。  这就是Dead Reference问题, 为了解决这个问题, 有两个方案:Phoenix Singleton和带寿命的Singleton.

Phoenix是通过一个_destroy的变量来检测Singleton是否被析构了, 如果被析构了, 又被别得对象调用,那么会再次生成此Singleton.  而带寿命的Singletons是通过atexit这个函数, 来注册不同的Singleton的析构函数。 这些析构函数会根据不同的Singleton的生命排序,来达到最终效果。

最后描述了多线程, Singleton属于全局对象,而全局对象属于共享资源,在多线程的世界一定会出问题。 介绍了一些办法解释。 (没有做过多线程的东西, 虽然看起来很简单,不过没啥感想)

不过,这章最令我感兴趣的地方是: 如果将Singleton的这些需求和策略分开,也就是第一章说的policy的分离办法, 这里, 将这些策略分为Creation, LifeTime, threadingModel3个policy, 最后可以用不同的策略来实现Singleton.  非常的棒, 是一个分离策略的好例子。如果能理解上述所有,那么使用Singleton自然很简单了, 不过如果没有工作在相当复杂的环境, 我想,可能也用不到这么复杂的技巧了,呵呵。贴以下SingletonHolder的实现:

  template
    <
        typename T,
        template <class> class CreationPolicy = CreateUsingNew,
        template <class> class LifetimePolicy = DefaultLifetime,
        template <class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL,
        class MutexPolicy = LOKI_DEFAULT_MUTEX
    >
    class SingletonHolder
    {
    public:

        ///  Type of the singleton object
        typedef T ObjectType;

        ///  Returns a reference to singleton object
        static T& Instance();
       
    private:
        // Helpers
        static void MakeInstance();
        static void LOKI_C_CALLING_CONVENTION_QUALIFIER DestroySingleton();
       
        // Protection
        SingletonHolder();
       
        // Data
        typedef typename ThreadingModel<T*,MutexPolicy>::VolatileType PtrInstanceType;
        static PtrInstanceType pInstance_;
        static bool destroyed_;
    };

非常简单, 只要实现了各种策略, 就会得到一个理想的Singleton. 尤其在复杂环境中,尤为好用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值