创建型设计模式-单例
原文链接 单例模式及特殊类的设计
创建类-特殊场景
一个不能被拷贝的类
点击查看代码
class Test
{
public:
Test(const Test &other) = delete;
Test &operator(const Test &other) = delete;
}
一个不能被继承的类
final
一个只能在栈上创建的类
点击查看代码
class StackOnly
{
public:
static StackOnly create() { return StackOnly(); }
void* operator new(size_t size) = delete;
void operator delete(void *p) = delete;
private:
StackOnly();
}
一个只能在堆上创建的类
私有化构造函数,自实现创建方法
点击查看代码
class HeapOnly
{
public:
static HeapOnly *create(){ return new HeadOnly(); }
private:
HeapOnly() = default;
}
私有化析构函数
先解释为什么这个方法可行。一般来说:
C++是静态绑定的语言,在编译时期,所有的非虚函数调用都必须分析完成。则当对象建立在栈上面时,是由编译器分配内存空间的,调用构造函数来构造栈对象。当对象使用完后,编译器会调用析构函数来释放栈对象所占的空间。编译器管理了对象的整个生命周期(具体过程为: 通过直接移动栈顶指针,挪出适当的空间,然后在这片内存空间上调用构造函数形成一个栈对象。使用这种方法,直接调用类的构造函数 )。所以,编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性(其实不光是析构函数,只要是非静态的函数,编译器都会进行检查)。如果类的析构函数是私有的,则编译器不会在栈空间上为类对象分配内存。 所以 析构函数私有化的类的设计可以保证只能用new命令在堆(heap)中创建对象。
点击查看代码
class HeapOnly
{
public:
void destroy() { delete this; }
private:
~HeapOnly() = default;
}
一个只能实例化一个对象的类
单例模式 Singleton pattern
单例
饿汉式
程序启动时即创建。
优点:代码简洁;
缺点:内存始终被占用的缺陷,拖慢启动效率;单例应用于多个类时,启动时构建顺序随机;
点击查看代码
class Singleton
{
public:
static Singleton& instance() {
return *m_unique_obj;
}
private:
Singleton() = default;
Singleton(const Singleton &other) = delete;
Singleton& operator=(const Singleton &other) = delete;
private:
static Singleton *m_unique_obj;
}
Singleton *Singleton::m_unique_obj = new Singleton();
另外需要知道的事
上述写法中唯一实例对象(全局静态变量)的构造为程序启动初始,而一个程序中所有的全局静态变量的构造和析构顺序是随机的,唯一的规律就是 构造和析构的顺序是相反的,但构造本身是没有规律可言的。
懒汉式
需要时才创建。
优点:节省内存,提升启动效率;按需进行构造;
缺点:代码较为复杂;
要注意多线程场景下的双重判断+锁来保证仅会唯一实例化一个对象。
点击查看代码
class Singleton
{
public:
static Singleton& instance_1(){
/* 锁+双重检验 */
if (!pObject){
mtx.lock();
if (!pObject)
pObject = new Singleton();
mtx.unlock();
}
return *pObject;
}
static Singleton& instance_2(){
/* 利用编译器对于静态局部变量的处理,保证了只有首次进入该函数块时才会进行static变量的构造 */
static Singleton ins;
return ins;
}
static void destroy(){
mtx.lock();
if (pObject){
delete pObject;
pObject = nullptr;
}
mtx.unlock();
}
private:
Singleton() = default;
Singleton(const Singleton &other) = delete;
Singleton &operator=(const Singleton &other) = delete;
private:
static Singleton *pObject;
static std::mutex mtx;
}
Singleton *Singleton::pObject = nullptr;
std::mutex Singleton::mtx;
两种实现方案,第二种会更为简洁,不易出错。

浙公网安备 33010602011771号