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

一、问题的提出
单例模式是设计模式中最为简单,最为常见、最容易实现也是最应该掌握的模式。
在基于对象的设计中我们可以通过一个全局变量来实现,在面向对象和面向过程结合的设计范式中,我们也还是通过一个全局变量实现这一点,但是当我们遇到了纯粹的面向对象的范式中,这一点只能通过单例魔术来实现了。
简单得来说,单例模式是让一个类只能生成一个对象
二、如何使用单例模式
1、我们都知道对象的生成特点有两个:
(1)开辟内存
(2)调用构造函数
那么怎么才能使一个类只生成一个对象呢?
第一种思路:我们可以让构造函数只被调用一次。
第二种思路:我们给一个标识,如果有对象,就返回,如果无对象就对象调用构造函数生成唯一的对象。
2、代码实现
无单例模式下如何处理

class Master
{
public:	
private:
	Master(char* name, int age,bool sex)
		:mname(new char[strlen(name) + 1]()), mage(age),msex(sex)
		{
			strcpy_s(mname, strlen(name) + 1,name);
		}
	char* mname;
	int mage;
	bool msex;
}
int main()
{
	Master m1("zhangsan", 50, true);
	Master m2("lisi", 40, true);
	return 0;
}

这样我们发现这段代码执行错误,根据封装的特性,私有的成员只允许在本类类中访问。我们现在提供一个接口来生成唯一的对象

class Master
{
public:
	Master getInstance(char* name, int age, bool sex)
	{
		if(pm == NULL)
		{
			pm = new Master(name, age, sex);
			//pm  唯一对象的标识
		}
		return *pm;
	}
private:
	Master(char* name, int age,bool sex)
		:mname(new char[strlen(name) + 1]()), mage(age),msex(sex)
		{
			strcpy_s(mname, strlen(name) + 1,name);
		}
	char* mname;
	int mage;
	bool msex;
	static Master* pm;//静态的成员变量
}
Master* Master::pm = NULL;
int main()
{
	Master* pm1 = Master::getInstance("zhangsan", 50, true);
	Master* pm1 = Master::getInstance("lisi", 60, true);
	Master* pm1 = Master::getInstance("wangwu", 40, true);
	return 0;
}

这样一个简单的单例模式就设计成功了。
三、单例模式不依赖任何场景的设计
这是一个完整的单例模式的设计

class SingleTon
{
public:
	static SingleTon* getInstance()
	{
		if(psing == NULL)//唯一对象没有生成
		{
			psing = new SingleTon();
		}
		return psing;
	}
private:
	SingleTon{}
	SingleTon(const SingleTon&);
	static SingleTon* psing;
};
SingleTon* SingleTon::psing = NULL;
int main()
{
	//SingleTon singlel;
	SingleTon* psingle1 = SingleTon::getIntance();
	SingleTon* psingle2 = SingleTon::getIntance();
	SingleTon* psingle3 = SingleTon::getIntance();
	return 0;
}

四、单例模式的优化
1、上面的单例模式是线程不安全的单例模式,我们通过加锁使得单例模式线程安全

class SingleTon
{
public:
	static SingleTon* getInstance()
	{
		lock()
		if(psing == NULL)//唯一对象没有生成
		{
			psing = new SingleTon();
		}
		unlock();
		return psing;
	}
private:
	SingleTon{}
	SingleTon(const SingleTon&);
	static SingleTon* psing;
};
SingleTon* SingleTon::psing = NULL;

但是加锁解锁又会有额外的开销产生,浪费资源。所以我们加双重锁
2、双重锁机制的单例模式

class SingleTon
{
public:
	static SingleTon* getInstance()
	{
		if(psingle == NULL)
		{
			lock()
			if(psing == NULL)//唯一对象没有生成
			{
				psing = new SingleTon();
			}
			unlock();
	   }
			return psing;
	}
private:
	SingleTon{}
	SingleTon(const SingleTon&);
	static SingleTon* psing;
};
SingleTon* SingleTon::psing = NULL;

五、懒汉模式和饿汉模式
1、懒汉模式又称延时加载
使用时才生成唯一对象
懒汉模式可能会存在线程不安全的情况
懒汉模式也就是我们上面所写的加锁的单例模式(四(1))
2、饿汉模式又称贪婪加载
对象提前生成
饿汉模式解决了线程不安全的情况
线程是进程的执行路径,我们只要在分线程之前将唯一对象的生成完成,这样就保证了线程的安全

class SingleTon
{
public:
	static SingleTon* getInstance()
	{
		return psing;
	}
private:
	SingleTon(){}
	SingleTon(const SingleTon&);
	static SingleTon* psing;
};
 SingleTon*  SingleTon::psing = new  SingleTon();//main函数执行前
 int main()
 {
 	SingleTon* ps1 = SingleTon::getIntance();
	SingleTon* ps2 = SingleTon::getIntance();
	SingleTon* ps3 = SingleTon::getIntance();
	return 0;
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值