设计模式的C++实现 1.单例模式
来源:互联网 发布:ih5软件下载 编辑:程序博客网 时间:2024/05/16 21:06
单例模式即实现单例类,即系统中一个类只有一个实例,而且该实例易于外界访问。这样方便对实例个数进行控制并节约系统资源。
而单例常用与一些非局部静态对象,对于这些对象,程序难以控制,对于这些存在与全局,且一般持久存在的对象,有时需要按照一定约束或顺序来进行初始化,而初始化这些对象如果不使用单例方法的话会极度不安全。这个时候就要使用单例模式来解决这个问题。
实现单例的方法有很多,最简单的一个是将对象放入函数中作为其静态成员:
class SingleTon;SingleTon* getSingleTonInstance(){static SingleTon* instance = new SingleTon(); return instance;}class SingleTon{friend SingleTon* getSingleTonInstance();private:SingleTon(){}};这是我认为的最简单的实现单例模式的方法,不足的地方在于这个获得单例对象的函数不在类内。首先要实现单例模式,将构造函数声明为稀有,这样构造函数就不能被方法,也不能随意创建单例类的对象。而这里获得实例为函数的静态对象,所以其只有一个,且存在时间为创建到程序结束。
当然,也可以将函数中的静态对象改为类中的静态对象,而将这个全局的函数设置为类中的静态函数,这样就得到一个更加普遍常用的形式:
class SingleTon{public:static SingleTon* getInstance(){static SingleTon* instance = new SingleTon();return instance;}~SingleTon(){}private:SingleTon(){}SingleTon(const SingleTon&);SingleTon& operator=(const SingleTon&);};这里还是使用了函数中的静态成员,使用类中的静态成员也是可以的:
class SingleTon{public:static SingleTon* getInstance(){if(NULL == instance)instance = new SingleTon();return instance;}private:SingleTon(){}SingleTon(const SingleTon&);SingleTon& operator=(const SingleTon&);static SingleTon* instance;};SingleTon* SingleTon::instance;// = new SingleTon();类内的静态成员初始化可以调用类中的私有的构造函数。
为了安全性,这里将复制构造函数和赋值操作符都给隐藏了,但是析构函数还是可见的,程序员还是会误用delete来删除这个单例实体,这样是不安全的,可以选择将析构函数放入私有中,隐藏析构函数,对于一些对象在最后结束时析构,则不用关心其释放过程。
但是如果在程序执行中要调用析构函数进行实例的删除的话,就使用一个公有的函数来封装析构函数,且将析构函数置为私有:
class SingleTon{public:static SingleTon* getInstance(){if(NULL == instance)instance = new SingleTon();return instance;}static void delelteInstance(){if(NULL != instance){delete instance;instance = NULL;}}private:SingleTon(){}SingleTon(const SingleTon&);SingleTon& operator=(const SingleTon&);static SingleTon* instance;~SingleTon();};SingleTon* SingleTon::instance ;
这里就已经基本上在单线程上安全了,然后就考虑多线程,当多个线程企图同时初始化 单例实例时,就出现了问题,要使用互斥来解决问题,这里就使用临界区来解决:
CRITICAL_SECTION cs;class SingleTon{public:static SingleTon* getInstance(){if(NULL == instance){EnterCriticalSection(&cs); if(NULL == instance){//双检锁,在进入临界区后再检测一次是否对象已经建立instance = new SingleTon();}LeaveCriticalSection(&cs); }return instance;}static void delelteInstance(){if(NULL != instance){EnterCriticalSection(&cs);if(NULL != instance){delete instance;instance = NULL;}LeaveCriticalSection(&cs); }}private:SingleTon(){}SingleTon(const SingleTon&);SingleTon& operator=(const SingleTon&);static SingleTon* instance;~SingleTon();};SingleTon* SingleTon::instance ;这里使用双检锁的机制,第一次是判断是否需要对实例进行操作,第二次是在进入临界区即对数据加锁后,判断在数据已经不会再被外界干扰的情况下,第一次判断和第二次判断之间是否被其他线程进行了操作,这样两次判断保证了实例的安全。
但是这样还是不够安全,因为多线程中还是会有一些特殊情况,在类中一些文件被锁了,如文件句柄,数据库连接等,这些随着程序的关闭并不会立即关闭资源,必须要在程序关闭前,进行手动释放。这里的指不会自动关闭,是对于析构函数是私有的情况下,由于系统无法访问私有的析构函数,对于没有这些连接时,即类只在内存中占据了一些地址,则系统将其视为全局变量,在结束时释放其所在内存资源,所以没有内存泄漏。而若类中有文件句柄和数据库连接这些东西,系统并不会帮忙关闭这些,所以必须手动的调用析构函数中对这些文件的关闭操作。
对于这样的情况,一般会使用一种私有内嵌类Garbo,意为垃圾工人,在单例类中包含一个私有的静态垃圾工人对象,当程序结束时,系统会调用这个对象的析构函数,而这个析构函数中对单例类对象实现析构。
CRITICAL_SECTION cs;class SingleTon{public:static SingleTon* getInstance(){if(NULL == instance){EnterCriticalSection(&cs); if(NULL == instance){//双检锁,在进入临界区后再检测一次是否对象已经建立instance = new SingleTon();}LeaveCriticalSection(&cs); }return instance;}static void delelteInstance(){if(NULL != instance){EnterCriticalSection(&cs);if(NULL != instance){delete instance;instance = NULL;}LeaveCriticalSection(&cs); }}private:SingleTon(){}SingleTon(const SingleTon&);SingleTon& operator=(const SingleTon&);static SingleTon* instance;~SingleTon(){}//相应的关闭连接等操作class GarBo{public:~GarBo(){if(NULL != instance){EnterCriticalSection(&cs);if(NULL != instance){delete instance;instance = NULL;}LeaveCriticalSection(&cs); }}};static GarBo gc ;};SingleTon* SingleTon::instance ;SingleTon::GarBo SingleTon::gc;//类外的初始化。这样就获得一个比较完美的单例类了。
- 设计模式--单例模式 C++实现
- Objective-c 实现单例设计模式
- 设计模式的C++实现 1.单例模式
- 单例模式的设计(C++)
- 单例设计模式的实现代码
- java单例设计模式的实现
- 单例设计模式的实现
- 设计模式 - 线程安全的单例模式(C#)
- (C#)设计模式 之 单例模式
- 设计模式之单例模式(C++)
- 设计模式(C++) -----单例模式
- 【设计模式C++】单例模式
- 单例设计模式(C#) 简单模式
- 单例设计模式(C#) 懒汉模式
- C#--设计模式之单例模式
- 【Objective-C】单例模式的实现
- Objective-C 单例模式的实现
- c++--Singleton单例模式的实现
- report for the lecture"How Real is Real Enough", on Oct.9th
- 【iOS开发-38】为什么在用storyboard打开Assistant Editor时默认是.m文件?
- ExpandableListview
- 滑动事件的处理。(viewpager作为listview头时事件的处理)
- VS2008打包(含水晶报表)与安装注意事项
- 设计模式的C++实现 1.单例模式
- springmvc+easyui实现透视表-动态生成列
- Pomelo 学习
- linux 学习路线
- Codeforces 328B-Sheldon and Ice Pieces(贪心)
- 终于要开始了
- WEB程序设计之HTML(一)
- 远方的你还好吗
- 重构练习2:“疯狂连连看”程序中算法简化