【C++】设计模式之单例模式

文章目录

    • 概念
    • 饿汉模式
    • 懒汉模式
    • 饿汉模式和懒汉模式的优缺点

概念

单例模式一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全
局访问点该实例被所有程序模块共享

单例模式的实现分为饿汉模式和懒汉模式


饿汉模式

程序启动时创建一个唯一的实例对象去加载所有的资源(预加载)

  • 构造函数私有化
  • 防拷贝
  • 在类内创建一个静态对象,静态对象是属于类的,唯一的一份,符合单例模式的要求
  • 提供一个静态接口,返回对象的指针或者引用

在静态区创建对象

class Singleton {
public:
	static Singleton& GetInstance(){
		return _inst;
	}

private:
	//构造函数私有化
	Singleton(){}

	//防拷贝
	Singleton(const Singleton&) = delete;
	Singleton operator=(Singleton) = delete;

	//创建静态对象,保证只有一个对象
	static Singleton _inst;
};
Singleton Singleton::_inst;

在堆上创建对象

class Singleton {
public:
	static Singleton* GetInstance() {
		return _inst;
	}

private:
	//构造函数私有化
	Singleton() {}

	//防拷贝
	Singleton(const Singleton&) = delete;
	Singleton operator=(Singleton) = delete;

	//创建静态对象,保证只有一个对象
	static Singleton* _inst;
};
Singleton* Singleton::_inst = new Singleton;

饿汉模式是在类加载阶段就已经完成了对象的初始化,所以饿汉模式不存在线程安全问题

但是正因为如此,如果单例对象构造十分耗时或者占用很多资源,比如加载插件啊, 初始化网络连接啊,读取文件啊等等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化,就会导致程序启动时非常的缓慢。 所以这种情况使用懒汉模式延迟加载)更好


懒汉模式

堆区版本的懒汉模式

  • 构造函数私有化
  • 防拷贝
  • 创建一个静态对象指针,提供一个静态接口
  • 调用这个静态接口的时候,如果还没有创建对象,就new一个对象返回对象地址,如果对象已经存在,就什么都不做
  • 在进行对象是否存在的判断时,要保证线程安全
  • 如果要对创建的对象进行释放,可以添加一个静态del函数,或者添加一个垃圾回收类,在对象生命周期结束时自动释放资源
class Singleton {
public:
	static Singleton* GetInstance() {

		//双检查,在没有对象创建的时候才去获取锁,创建对象
		if (_inst == nullptr) {
			_mtx.lock();
			if (_inst == nullptr) {
				_inst = new Singleton;
			}
			_mtx.unlock();
		}
		return _inst;
	}

	static void DelInstance() {

		_mtx.lock();
		if (_inst) {
			delete _inst;
			_inst = nullptr;
		}
		_mtx.unlock();
	}

	// 实现一个内嵌垃圾回收类
	class CGarbo {
	public:
		~CGarbo() {
			if (_inst) {
				delete _inst;
				_inst = nullptr;
			}
		}
	};

private:
	//构造函数私有化
	Singleton() {}

	//防拷贝
	Singleton(const Singleton&) = delete;
	Singleton operator=(Singleton) = delete;

	//创建静态对象,保证只有一个对象
	static Singleton* _inst;
	static mutex _mtx;
	static CGarbo _cg;
};
Singleton* Singleton::_inst = nullptr;
mutex Singleton::_mtx;
Singleton::CGarbo Singleton::_cg;

静态区版本的懒汉模式

class Singleton {
public:
	static Singleton& GetInstance() {

		static Singleton inst;
		return inst;
	}

private:
	//构造函数私有化
	Singleton() {}

	//防拷贝
	Singleton(const Singleton&) = delete;
	Singleton operator=(Singleton) = delete;

};

这种方法不必考虑线程安全问题,编写十分简单

这种方式有一些缺陷

  • 对象创建在静态区,如果对象太大就不适合用这种方法
  • 无法手动释放资源,只有对象生命周期到期时才会自动释放

饿汉模式和懒汉模式的优缺点

饿汉模式

优点

  • 简单

缺点

  • 程序启动时候就要加载资源,如果需要初始化的资源过大,就会导致程序的启动速度变慢,影响用户体验
  • 如果有多个单例类,假设之间存在着依赖关系,例如B依赖A,要求A单例先创建初始化,B单例再创建初始化,此时就不能够使用饿汉模式,因为无法保证其初始化顺序,而使用懒汉模式则可以手动控制

懒汉模式

优点

  • 延迟加载,程序启动的时候不会初始化类不会影响程序的启动速度
  • 可以手动控制类的初始化顺序

缺点

  • 需要考虑判断的线程安全问题,效率会有所降低
  • 编写较为复杂

你可能感兴趣的:(C++,单例模式,c++,设计模式)