单例模式

来源:互联网 发布:淘宝直通车排名规则 编辑:程序博客网 时间:2024/05/31 15:18

比较几种常见的单例模式实现

方法一:

#include<iostream>using namespace std;class Singleton{private:Singleton():Data(0)   //构造函数声明为私有{}static Singleton * Instance;public:static Singleton & GetInstance();int Data;//用于测试};Singleton * Singleton::Instance=NULL;Singleton & Singleton::GetInstance(){if(Instance == NULL)  //判断是否实例已经存在{Instance = new Singleton();}return *Instance;}int main(void){Singleton& singletonObj1=Singleton::GetInstance();cout<<singletonObj1.Data<<endl;singletonObj1.Data=1;cout<<singletonObj1.Data<<endl;Singleton& singletonObj2=Singleton::GetInstance();cout<<singletonObj2.Data<<endl;//通过观测此次输出的结果可知,singletonObj1与singletonObj2是同一对象singletonObj2.Data=2;cout<<singletonObj2.Data<<endl;return 0;}

方法一是最基本的实现了单例模式。

方法二:

#include<iostream>using namespace std;class Singleton{private:Singleton():Data(0)   //构造函数声明为私有{}static Singleton * Instance;public:static Singleton & GetInstance();int Data;//用于测试};Singleton * Singleton::Instance=NULL;Singleton & Singleton::GetInstance(){if(Instance == NULL)  //判断是否实例已经存在{lock();//需要另外实现if (Instance==NULL){Instance = new Singleton();}unlock();//需要另外实现}return *Instance;}int main(void){Singleton& singletonObj1=Singleton::GetInstance();cout<<singletonObj1.Data<<endl;singletonObj1.Data=1;cout<<singletonObj1.Data<<endl;Singleton& singletonObj2=Singleton::GetInstance();cout<<singletonObj2.Data<<endl;//通过观测此次输出的结果可知,singletonObj1与singletonObj2是同一对象singletonObj2.Data=2;cout<<singletonObj2.Data<<endl;return 0;}

方法二相对于方法一,增加了多线程安全


方法三:

#include<iostream>using namespace std;class Singleton{private:Singleton():Data(0)   //构造函数声明为私有{}static Singleton * Instance;public:static Singleton & GetInstance();int Data;//用于测试};Singleton * Singleton::Instance=new Singleton();Singleton & Singleton::GetInstance(){return *Instance;}int main(void){Singleton& singletonObj1=Singleton::GetInstance();cout<<singletonObj1.Data<<endl;singletonObj1.Data=1;cout<<singletonObj1.Data<<endl;Singleton& singletonObj2=Singleton::GetInstance();cout<<singletonObj2.Data<<endl;//通过观测此次输出的结果可知,singletonObj1与singletonObj2是同一对象singletonObj2.Data=2;cout<<singletonObj2.Data<<endl;return 0;}
方法三的实例在程序启动时就已经创建,因此在每次获取的时候就不需要进行任何的判断。


方法四:

#include<iostream>
using namespace std;class Singleton{private:Singleton():Data(0)   //构造函数声明为私有{}//Singleton(const Singleton&);//Singleton& operator=(const Singleton&);public:static Singleton & GetInstance();int Data;//用于测试};Singleton & Singleton::GetInstance(){static Singleton Instance;return Instance;}int main(void){Singleton& singletonObj1=Singleton::GetInstance();cout<<singletonObj1.Data<<endl;singletonObj1.Data=1;cout<<singletonObj1.Data<<endl;Singleton& singletonObj2=Singleton::GetInstance();cout<<singletonObj2.Data<<endl;//通过观测此次输出的结果可知,singletonObj1与singletonObj2是同一对象singletonObj2.Data=2;cout<<singletonObj2.Data<<endl;return 0;}
方法四将实例指定为静态局部变量,它是在第一次调用Singleton::GetInstance()时创建。其为局部静态变量,不是new出来的,在程序结束时能自动销毁,不用delete。但是其存在的一个问题就是,如果不是用引用调用此静态函数,而是Singleton singletonObj3=Singleton::GetInstance(),此句是调用复制构造函数,用GetInstance()返回的静态变量的值对singletonObj3对象初始化(此时在内存中有两个对象,静态对象和singletonObj3),为了防止此问题出现,应该也显示声明复制构造函数为私有。还有一个问题就是自我赋值,singletonObj1=singletonObj2,两者是同一个东西,为了防止此情况出现,我们可以在重载赋值操作中判断是否为同一个对象,但是单例模式中永远只有一个对象,那么我们干脆就显示声明赋值操作为私有既可。

即在类中把那两句注释消去,其实就是在编译中禁止了以上所说的两种操作,如果使用了,编译器会报错。


可以看出方法一、二、三都存在缺少delete的问题。

正常项目中,全局实例只有一个,在程序结束时,系统会释放内存资源,所以没有delete的问题并不大,不会发生内存泄露。但是在对象有 操作文件 或者 连接数据库 时,程序关闭时不会立即关闭资源,就需要在程序关闭前,手动释放资源。由于都是静态变量,因此不能使用类的析构函数对它进行销毁,有些人就想出了使用嵌套类专门处理释放资源。在方法一中加入嵌套类Garbo

class Singleton{private:Singleton():Data(0)   //构造函数声明为私有{}static Singleton * Instance;public:static Singleton & GetInstance();int Data;//用于测试class Garbo //它的唯一工作就是在析构函数中删除CSingleton的实例{public:~Garbo(){if( Singleton::Instance )delete Singleton::Instance;}};static Garbo Garbo; //定义一个静态成员,程序结束时,系统会自动调用它的析构函数};Singleton * Singleton::Instance=NULL;Singleton & Singleton::GetInstance(){if(Instance == NULL)  //判断是否实例已经存在{Instance = new Singleton();}return *Instance;}
需要更详细的内容可以参考 果冻想 http://www.jellythink.com/archives/82
0 0
原创粉丝点击