C++设计模式粗略整理

C++设计模式粗略整理

单例模式

  • 所谓单例模式,指的是单一一个单例类,这个类只能有一个实例
  • 可以通过类的私有静态指针指向类的唯一实例,并且用一个共有的静态方法获取该实例,把构造函数定义为protected或者private
  • 懒汉式的意思就是懒,在调用的时候才创建实例,延迟加载
//懒汉式-基础实现版
#include <iostream>
using namespace std;
class Singelton {
private:
	Singleton(){}//私有构造函数,无法通过正常方法声明对象
	static Singleton* _instance;//单例模式中仅有的实例,使用私有静态指针指向它
public:
	static Singleton getInstance() {//提供一个接口用于创建单例,可知单例创建后再次调用的话返回的还是之前创建的实例
		if(_instance==NULL) {
			_instance=new Singleton();//虽然构造私有化了,但是类内部还是可以创建对象
		}
		return _instance;
	}
};

上面的实现存在内存泄漏的问题,_instance没有释放掉

//懒汉式-改进版
#include <iostream>
using namespace std;
class Singelton {
private:
	Singleton(){}//私有构造函数,无法通过正常方法声明对象
	static Singleton* _instance;//单例模式中仅有的实例,使用私有静态指针指向它
	class del {//定义一个内部类
	public:
		~del(){
			if(Singleton::_instance!=NULL) {
				delete Singleton::_instance;
				Singleton::_instance=NULL;
			}
		}
	}
	static del d;//定义一个私有静态内部类的对象,在程序结束的时候,del析构实现_instance的释放
public:
	static Singleton getInstance() {//提供一个接口用于创建单例,可知单例创建后再次调用的话返回的还是之前创建的实例
		if(_instance==NULL) {
			_instance=new Singleton();//虽然构造私有化了,但是类内部还是可以创建对象
		}
		return _instance;
	}
};

然后上面的实现还是不完美,在多线程的情况下,因为if(_instance==NULL)不是原子操作,所以在一个线程判断了之后,还没来得及返回创建的对象时,另一个线程可能又进了判断创建了对象

//懒汉式-线程版
#include <iostream>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
using namespace std;
class Singelton {
private:
	Singleton(){}//私有构造函数,无法通过正常方法声明对象
	static Singleton* _instance;//单例模式中仅有的实例,使用私有静态指针指向它
	class del {//定义一个内部类
	public:
		~del(){
			if(Singleton::_instance!=NULL) {
				delete Singleton::_instance;
				Singleton::_instance=NULL;
			}
		}
	}
	static del d;//定义一个私有静态内部类的对象,在程序结束的时候,del析构实现_instance的释放
public:
	static Singleton getInstance() {//提供一个接口用于创建单例,可知单例创建后再次调用的话返回的还是之前创建的实例
		pthread_mutex_lock(&lock);
		if(_instance==NULL) {
			_instance=new Singleton();//虽然构造私有化了,但是类内部还是可以创建对象
		}
		pthread_mutex_unlock(&lock);
		return _instance;
	}
};

即便是现在,在大量线程的情况下,依然有着效率不高的问题,因为一个互斥锁同时只能被一个线程占用

//懒汉式-线程加强版
#include <iostream>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
using namespace std;
class Singelton {
private:
	Singleton(){}//私有构造函数,无法通过正常方法声明对象
	static Singleton* _instance;//单例模式中仅有的实例,使用私有静态指针指向它
	class del {//定义一个内部类
	public:
		~del(){
			if(Singleton::_instance!=NULL) {
				delete Singleton::_instance;
				Singleton::_instance=NULL;
			}
		}
	}
	static del d;//定义一个私有静态内部类的对象,在程序结束的时候,del析构实现_instance的释放
public:
	static Singleton getInstance() {//提供一个接口用于创建单例,可知单例创建后再次调用的话返回的还是之前创建的实例
		if(_instance==NULL){
			pthread_mutex_lock(&lock);
			if(_instance==NULL) {
				_instance=new Singleton();//虽然构造私有化了,但是类内部还是可以创建对象
			}
			pthread_mutex_unlock(&lock);
		}
		return _instance;
	}
};

这样的实现,只有没有Singleton实例时才会进入加锁的代码

  • 饿汉式,在一开始就创建实例,要用的时候直接返回
  • 饿汉式就没有线程安全的问题,因为实例已经创建,所有线程只能访问同一个对象
  • 对象是一个私有的静态变量(不是指针),程序结束会自动析构,不用考虑内存泄漏问题
//饿汉式-基础版
#include <iostream>
using namespace std;
class Singleton {
private:
	Singleton(){}
	static Singleton instance;
public:
	static Singleton& getInstance() {
		return instance;
	}
};

但是上面的实现存在一个问题,Singleton singleton=Singleton::getInstance();这么做的话就出现了一个类拷贝的问题,产生原因在于,类内没有实现拷贝构造函数,编译器会为类自动生成一个默认的拷贝构造函数
解决方法:

  1. 自己定义一个拷贝构造函数和operator=,但是函数内什么都不做
  2. 返回一个Singleton指针
//饿汉式-改进版
#include <iostream>
using namespace std;
class Singleton {
private:
	Singleton(){}
	static Singleton instance;
public:
	static Singleton* getInstance() {
		return &instance;
	}
};

总结:单例模式适用于只允许一个实例存在的情况,它的实现必须满足三个条件,一是必须在类中就定义一个实例;二是必须有一个公有的静态方法来获取该实例;三是构造函数必须是私有的,来保证不容许别人通过调用构造函数来生成一个实例。在实现时要注意内存泄露问题,线程安全问题,性能问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值