C++单例模式深度剖析 二

在程序中可能有多个单例,有没有什么方法可以只实现一次单例而能够复用其代码从而实现多个单例呢? 答案是肯定的,代码复用技术有两种典型方法:

  • 模板技
  • 继承

■ 单例类的模板

● 奇异递归模板模式(CRTP ,Curiously recurring template pattern)

代码示例如下:

#include <iostream>
using namespace std;

template<typename T>class MySingleton
{
public:
    static T& getInstance()
    {
        static T instance;
        return instance;
    }
    virtual ~MySingleton()
    {
        cout << "This is destructor!" << endl;
    }
    MySingleton(const MySingleton&) = delete;
    MySingleton& operator=(const MySingleton&) = delete;
protected:
    MySingleton()
    {
        cout << "This is constructor!" << endl;
    }
};

class DerivedSingleton : public MySingleton<DerivedSingleton>
{
   friend class MySingleton<DerivedSingleton>;
public:
   DerivedSingleton(const DerivedSingleton&) = delete;
   DerivedSingleton& operator=(const DerivedSingleton&) = delete;
private:
   DerivedSingleton() = default;
};

int main()
{
    DerivedSingleton& instance1 = DerivedSingleton::getInstance();
    DerivedSingleton& instance2 = DerivedSingleton::getInstance();
    return 0;
}

以上实现单例的模板基类,使用方法如例所示,子类需要将自己作为模板参数 T 传递给 MySingleton< T >模板; 同时需要将基类声明为友元,这样才能调用子类的私有构造函数。

■ 基类模板要点:

  1. 构造函数必须是 protected才能继承;
  2. 使用了CRTP(奇异递归模板模式)
  3. 在这里基类的析构函数可以不需要 virtual ,因为子类在应用中只会用 DerivedSingleton类型,保证析构时和构造时的类型一致
● 不需要在子类声明友元的实现(使用代理类令牌token)

核心在于使用一个代理类令牌 token,子类构造函数需要传递token才能构造,但是把 token保护其起来, 然后子类的构造函数就可以是公有的了,这个子类只有 DerivedSingleton(token)这样的构造函数,用户便无法自己定义一个类的实例了,起到控制其唯一性的作用。代码如下:

#include <iostream>
using namespace std;

template<typename T>class MySingleton
{
public:
    static T& getInstance() noexcept(is_nothrow_constructible<T>::value)
    {
        static T instance{token()};
        return instance;
    }
    virtual ~MySingleton() = default;
    MySingleton(const MySingleton&) = delete;
    MySingleton& operator=(const MySingleton&) = delete;
protected:
    struct token{}; 	// helper class
    MySingleton() noexcept = default;
};

class DerivedSingleton: public MySingleton<DerivedSingleton>
{
public:
   DerivedSingleton(token)
   {
       cout << "This is constructor!" << endl;
   }

   ~DerivedSingleton()
   {
       cout << "This is destructor!" << endl;
   }
   DerivedSingleton(const DerivedSingleton&) = delete;
   DerivedSingleton& operator=(const DerivedSingleton&) = delete;
};

int main()
{
    DerivedSingleton& instance_1 = DerivedSingleton::getInstance();
    DerivedSingleton& instance_2 = DerivedSingleton::getInstance();
    return 0;
}

更多设计模式,请关注:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值