单例模式保证一个类仅有一个实例,并提供一个访问它的全局访问点,其类图如下图所示:
在《设计模式 可服用面向对象软件的基础》一书中给出过C++中实现单例模式的经典实现,但书中给出的实现有着下面的不足:
- 未使用模版技术,无法将单例模式类与具体类分离,从而无法方便的将任何类设置为单例类
- 未使用智能指针技术,需要手动释放内存
而本文的代码的实现中则通过C++11的以下机制克服了上面的缺点:
- 使用可变参数模版技术,使得单例模式支持任意参数的构造函数
- 使用类模板技术,支持以非继承的方式将任意类转为“单例类”
- 使用智能指针技术,无需担心单例对象内存的释放
- 也支持通过继承的方式,使得子类为单例类
下面代码的实现参考《深入应用C++11 代码优化与工程级应用》
//// MySingleton.h// Created by Yyh on 2022/3/13.#ifndef _MySingleton_h_#define _MySingleton_h_#include <memory>template <typename T>class MySingleton{public://初始化单例template<typename ... Args>static std::shared_ptr<T> Instance(Args &&... args){m_pInstance = std::make_shared<T>(std::forward<Args>(args)...); //完美转发return m_pInstance;}//获取单例static std::shared_ptr<T> GetInstance(){if(m_pInstance == nullptr){//如果未初始化的前提下获取单例则抛出异常throw std::logic_error("the instance is not init, please initialize the instance first");}return m_pInstance;}protected:virtual ~MySingleton(){}MySingleton(){}private:static std::shared_ptr<T> m_pInstance;};template <class T>std::shared_ptr<T> MySingleton<T>::m_pInstance = nullptr;#endif
下面是测试函数:
#include <iostream>#include "MySingleton.h"using namespace std;struct A{A(){strText = "A()";}std::string strText;};struct B{B(std::string strParam){strText = std::string("B(") + strParam + ")";}std::string strText;};struct C : public MySingleton<C>{std::string strText;C(std::string strParam){strText = std::string("C(") + strParam + ")";}};int main(int argc, char *argv[]) {MySingleton<A>::Instance();MySingleton<B>::Instance("b");C::Instance("c");cout << "A:" << MySingleton<A>::GetInstance()->strText << endl;cout << "B:" << MySingleton<B>::GetInstance()->strText << endl;cout << "C:" << C::GetInstance()->strText << endl;}
参考:
- 《深入应用C++11 代码优化与工程级应用》
- 《设计模式 可服用面向对象软件的基础》
