设计模式一:单例模式的原理,c++实现,以及应用实例

单例模式的由来(需求产生特性)

对于一般的方法类,例如计算数据中的众数,一般可以写一个专门的函数 f() 来方便我们调用。但是在面向对象编程的过程中,也应该将方法设计成类的方式。这里如果将 f() 放到类中,每一次调用都实例化出一个对象,也是可以完成需求的。但是这里调用的 f() 的功能完全一样,没有必要重新实例化对象,产生代码的冗余。

所以我们想创造出一个模式,让类的对象只有一个,并且全局可用,线程安全。

单例模式的两种实现方式

一 饿汉模式

为啥叫做饿汉模式?

因为此模式里面在类创建的时候就已经创建好了唯一的对象,不管有没有需求,它只负责进行创建以备使用。因为这种方式在需求提出前就做好了准备,可以类比人非常着急,称之为饿汉。
饿汉模式c++ 模板

//饿汉模式 
//线程安全
class Singleton {
public:
	static Singleton& getInstance() {	//公有的方法
		return instance;
	}
private:
	static Singleton instance ; //私有的实例 static:由类共享的成员变量
	Singleton() {		//私有的构造函数
		std::cout << "singleton construct" << std::endl;
	};
	~Singleton() {		//私有的析构函数
		std::cout << "singleton deconstruct" << std::endl;
	}
	Singleton& operator=(Singleton& other) = delete;	//禁止赋值运算符
	Singleton(Singleton& other) = delete;//禁止复制构造函数
};

Singleton Singleton:: instance;	//必须定义static

int main() {

	Singleton& one_copy = Singleton::getInstance();	//类的共有方法调用方式
	getchar();
	return 0;
	
}
如何保证,饿汉模式中实例一定会在调用前创建好?

在单线程中,static对象会在第一次程序执行到该对象的定义处遇到时初始化。所以是没问题的。
在多线程中,有线程安全问题,因为在线程里面,可能出现多个线程同时程序运行到一个类。但是我们定义的是一个静态对象,在程序运行之出就会进行分配空间、进行初始化。所以也没问题。

二 懒汉模式

为什么叫他懒汉模式?
因为“懒”,只有在需求出现的时候,才会创建对象或者返回对象。

class Singleton {
public:
	static Singleton* getInstance() {	//公有的方法 static必须使用static变量
		if (instance == nullptr) {
			instance = new Singleton();
		}
		return instance;
	}
private:
	static Singleton * instance ; //私有的实例 static:由类共享的成员变量
	Singleton() {		//私有的构造函数
		std::cout << "singleton construct" << std::endl;

	};
	~Singleton() {		//私有的析构函数
		std::cout << "singleton deconstruct" << std::endl;
	}
	//Singleton& operator=(Singleton& other) = delete;	//禁止赋值运算符
	Singleton(Singleton& other) = delete;//禁止复制构造函数
};

Singleton* Singleton::instance = nullptr;

int main() {
	Singleton* one_copy = Singleton::getInstance();	//类的共有方法调用方式
	Singleton* two_copy = Singleton::getInstance();	//类的共有方法调用方式
	getchar();
	return 0;
}

调用2次,但是只调用了一次构造函数
在这里插入图片描述

如何保证懒汉模式线程安全?

懒汉模式需要在程序运行过程中创建唯一的对象,所以保证线程互斥必须保证。
解决方式
双重锁检测

class Singleton {
public:
	static Singleton* getInstance() {	//公有的方法
		if (instance == nullptr) {
			g_lock.lock(); //上锁
			if (instance == nullptr)
			{
				instance = new Singleton();
			}
			g_lock.unlock();//解锁函数 
		}
		return instance;
	}
private:
	static Singleton * instance ; //私有的实例 static:由类共享的成员变量
	Singleton() {		//私有的构造函数
		std::cout << "singleton construct" << std::endl;

	};
	~Singleton() {		//私有的析构函数
		std::cout << "singleton deconstruct" << std::endl;
	}
	Singleton& operator=(Singleton& other) = delete;	//禁止赋值运算符
	Singleton(Singleton& other) = delete;//禁止复制构造函数
};
#include <iostream>
#include <thread>
#include <mutex>

using namespace std;
mutex g_lock;

class Singleton {
public:
	static Singleton* getInstance() {	//公有的方法
		if (instance == nullptr) {
			g_lock.lock(); //上锁
			if (instance == nullptr)
			{
				instance = new Singleton();
			}
			g_lock.unlock();//解锁函数 
		}
		return instance;
	}
private:
	static Singleton * instance ; //私有的实例 static:由类共享的成员变量
	Singleton() {		//私有的构造函数
		std::cout << "singleton construct" << std::endl;

	};
	~Singleton() {		//私有的析构函数
		std::cout << "singleton deconstruct" << std::endl;
	}
	Singleton& operator=(Singleton& other) = delete;	//禁止赋值运算符
	Singleton(Singleton& other) = delete;//禁止复制构造函数
};

Singleton* Singleton::instance = nullptr;
int main() {

	Singleton* one_copy = Singleton::getInstance();	//类的共有方法调用方式
	Singleton* two_copy = Singleton::getInstance();	//类的共有方法调用方式

	getchar();
	return 0;
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值