设计模式06-单例模式C++实现


一、单例模式

只能有一个类的对象,例如windows中的任务管理器,OS只需要维护这样一个对象即可,不需要每次都创建。使用单例模式来限制某个类创建实例对象的个数为1。

二、懒汉模式

在懒汉模式下,单例类的对象在需要的时候(调用 getInstance)才去创建

步骤如下:

1、构造函数私有化

由于不能在类外定义和 new,因此要将构造函数私有

2、类内提供私有的静态指针成员,并提供给外部创建对象的静态公有接口

由于构造函数私有了,那么提供的公有接口是没办法通过对象调用的,因此需要将该公有接口设为 static 的,又由于静态函数只能访问静态成员,因此类内私有的指针成员也需要设为 static 的,而为了防止在外部能访问到指针成员,造成可能的修改,因此需要将其设为私有属性,并在类外初始化为空

3、禁止构造、禁止拷贝

4、内存释放,嵌套一个回收类

不能提供接口供外部使用来释放,而是提供一个静态回收类,并在这个类的析构函数中释放掉单例类的指针成员,这样在程序结束时就会调用它的析构函数。

class SingletonLazy {
public:
	static SingletonLazy* getInstance() {
		if (_pSingle == nullptr)
			_pSingle = new SingletonLazy;
		return _pSingle;
	}

	struct Garbo {
		~Garbo() {
			if (_pSingle != nullptr)
				delete _pSingle;
		}
	};
private:
	SingletonLazy() { }
	SingletonLazy(const SingletonLazy& single) { } //禁止拷贝
	SingletonLazy& operator=(const SingletonLazy& single) { } // 禁止赋值
	static SingletonLazy* _pSingle;

	static Garbo _garbo;
};

SingletonLazy* SingletonLazy::_pSingle = nullptr;

void test1() {

	SingletonLazy* p1 = SingletonLazy::getInstance();
	SingletonLazy* p2 = SingletonLazy::getInstance();
	cout << "p1 : " << (int)p1 << endl;
	cout << "p2 : " << (int)p2 << endl;

	if (p1 == p2) {
		cout << "成功创建单例 SingletonLazy\n";
	}	
}

三、饿汉模式

饿汉模式在 main 函数之前就创建好了对象。

也就是将懒汉模式下的静态指针成员在类外初始化时就 new,这样一来 getInstance 方法中就不需要 new 了,直接返回即可


class SingletonHungry{
public:
	static SingletonHungry* getInstance() {
		return _pSingle;
	}

private:
	SingletonHungry() { }
	SingletonHungry(const SingletonHungry& single) { } //禁止拷贝
	SingletonHungry& operator=(const SingletonHungry& single) { } // 禁止赋值
	static SingletonHungry* _pSingle;
};

SingletonHungry* SingletonHungry::_pSingle = new SingletonHungry;

void test2() {
	SingletonHungry* p3 = SingletonHungry::getInstance();
	SingletonHungry* p4 = SingletonHungry::getInstance();
	cout << "p3 : " << (int)p3 << endl;
	cout << "p4 : " << (int)p4 << endl;

	if (p3 == p4) {
		cout << "成功创建单例 SingletonHungry\n";
	}
}

四、两种模式的线程安全性

在多线程的懒汉模式下,由于对象在需要时才调用 getInstance 创建,多个线程可能同时调用 getInstance, 结果创建了多个对象。

所以,懒汉模式是线程不安全的。而饿汉模式在 main 之前就创建好了,并在后面的 getInstance 调用中,返回的都是同一个对象,因此饿汉模式是线程安全的,在多线程情况下,通常都使用饿汉模式。

懒汉模式加锁实现线程安全

加锁,效率低一些。

#include <iostream>
#include <thread>
#include <mutex>
using namespace std;

class SingletonLazy {
public:
	static SingletonLazy* getInstance() {
		{
			lock_guard<mutex> lk(_mtx);
			if (_pSingle == nullptr)
				_pSingle = new SingletonLazy;
		}
		
		return _pSingle;
	}

private:
	SingletonLazy() { }
	SingletonLazy(const SingletonLazy& single) { } //禁止拷贝
	SingletonLazy& operator=(const SingletonLazy& single) { } // 禁止赋值
	static SingletonLazy* _pSingle;

	static mutex _mtx;
};

SingletonLazy* SingletonLazy::_pSingle = nullptr;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值