单例模式

来源:互联网 发布:网络舆情的最新发展 编辑:程序博客网 时间:2024/06/08 02:33

        单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。

        单例模式的要点有三个:一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。 

        C++单例模式有许多种实现方法,在C++中,甚至可以直接用一个全局变量做到这一点,但这样的代码显得很不优雅。《设计模式》一书中给出了一种很不错的实现,定义一个单例类,使用类的私有静态指针变量指向类的唯一实例,并用一个公有静态方法获取该实例。

如下:单例模式程序一:

Singleton.h文件:class CSingleTon{private:CSingleTon(); //构造函数为私有的public:~CSingleTon();//析构函数是公有的public:static CSingleTon* GetInstance();//用来获取实例,公有int GetVar();//获取m_num的值void SetVar(int var);//设置m_num的值void Print();           //在控制台上打印m_num的值private:static CSingleTon *m_pInstance; //类的唯一实例,私有int m_var;};


 

 

Singleton.cpp#include <iostream>using namespace std;#include "singleton.h"CSingleTon *CSingleTon::m_pInstance = CSingleTon::GetInstance();//静态成员变量的初始化CSingleTon::CSingleTon(){m_var = 0;}CSingleTon::~CSingleTon(){if(m_pInstance != NULL)delete m_pInstance;}void CSingleTon::SetVar(int var){m_var = var;}int CSingleTon::GetVar(){return m_var;}CSingleTon* CSingleTon::GetInstance(){if(m_pInstance == NULL){m_pInstance = new CSingleTon();}return m_pInstance;}void CSingleTon::Print(){cout<<m_var<<endl;}


 

Main.cpp#include <iostream>using namespace std;#include "singleton.h"int main(void){CSingleTon *tonfir = CSingleTon::GetInstance();CSingleTon *tonsec = CSingleTon::GetInstance();printf("%p\n%p\n", tonfir, tonsec); //打印两个单例类对象指针的地址tonfir->Print();tonfir->SetVar(5);tonsec->Print();delete tonfir;          //调用析构函数delete tonsec;//其实这句话可以不写,因为tonfir和tonsec指向的是同一个对象return 0;}

该单例类的特征:

       1.它有一个唯一实例的静态指针变量m_pInstance,并且是私有的;

       2.它有一个公有函数,用于获取这个唯一实例,并在需要的时候创建该实例;

       3.它的构造函数是私有的,这样就不能在别处创建该类的实例

       大多时候,这样的实现都不会出现问题。有经验的读者可能会问,m_pInstance指向的空间什么时候释放呢?更严重的问题是,这个实例的析构操作什么时候执行?如果在类的析构行为中有必须的操作,比如关闭文件,释放外部资源,那么上面所示的代码无法实现这个要求。我们需要一种方法,正常地删除该实例。

         可以在程序结束时调用GetInstance并对返回的指针调用delete操作。这样做可以实现功能,但是不仅很丑陋,而且容易出错。因为这样的附加代码很容易被忘记,而且也很难保证在delete之后,没有代码再调用GetInstance函数。

         一个妥善的方法是让这个类自己知道在合适的时候把自己删除。或者说把删除自己的操作挂在系统中的某个合适的点上,使其在恰当的时候自动被执行。

         我们知道,程序在结束的时候,系统会自动析构所有的全局变量。事实上,系统也会析构所有的类的静态成员变量,就像这些静态成员也是全局变量一样。利用这个特征,我们可以在C++单例模式类中定义一个这样的静态成员变量,而它的唯一工作就是在析构函数中删除单例类的实例。如下面的代码中的CGarbo类(Garbo意为垃圾工人)

Singleton.h#pragma onceclass CSingleTon{private:CSingleTon(); //构造函数为私有的public:           //析构函数要是公有的~CSingleTon();private:static CSingleTon *m_pInstance;      //类的唯一实例class CGarbo//内部类,该类的唯一工作是在析构函数中删除CSingleTon的实例{public:~CGarbo(){//if(CSingleTon::m_pInstance)             //内部类不能去访问包含其类的非公有成员变量//delete CSingleTon::m_pInstance;if(CSingleTon::GetInstance())delete CSingleTon::GetInstance();}};static CGarbo Garbo;//定义一静态成员,在程序结束时,系统会调用它的析构函数protected:int m_num;public:static CSingleTon* GetInstance(); //用来获取实例void SetNum(int num);  //设置m_num的值int GetNum();          //获取m_num的值void PrintNum();       //在控制台上打印m_num的值};


Singleton.cpp#include "singleton.h"#include <iostream>using namespace std;CSingleTon *CSingleTon::m_pInstance = CSingleTon::GetInstance();//静态成员变量的初始化CSingleTon::CSingleTon(){cout<<"Construct"<<endl;this->m_num = 0;}CSingleTon::~CSingleTon(){cout<<"Destruct"<<endl;if(m_pInstance != NULL)delete m_pInstance;}CSingleTon* CSingleTon::GetInstance(){if(m_pInstance == NULL){m_pInstance = new CSingleTon();}return m_pInstance;}void CSingleTon::SetNum(int num){this->m_num = num;}int CSingleTon::GetNum(){return this->m_num;}void CSingleTon::PrintNum(){cout<<this->m_num<<endl;}

 

Main.cpp#include <iostream>using namespace std;#include "singleton.h"int main(void){CSingleTon *tonfir = CSingleTon::GetInstance();CSingleTon *tonsec = CSingleTon::GetInstance();tonfir->PrintNum();tonsec->PrintNum();tonfir->SetNum(5);tonsec->PrintNum();return 0;}


 

原理:

         程序运行结束时,系统自动析构所有的全局变量。也会析构所有类的静态成员变量。

         在程序运行结束时,系统会调用CSingleTon的静态成员Garbo的析构函数,该析构函数会删除单例的唯一实例。

使用这种方法释放单例对象有以下特征:

         1.在单例类内部定义专有的嵌套类

         2.在单例类内部定义私有的专门用于释放单例对象的静态成员

         3.利用程序在结束时,析构静态变量的特性,选择最终的释放时机

         4.使用C++单例模式的代码不需要任何操作,不必关心对象的释放


 

原创粉丝点击