你的位置:首页 > ASP.net教程

[ASP.net教程]C++单例模式实例


定义:在某些情况下,我们设计中的对象只需要一个,比方说:线程池(threadpool)、缓存(cache)、对话框、处理偏好设置和注册表对象、日志对象、充当打印机、显卡等设备的驱动程序的对象等。事实上,这类对象只能有一个实例,如果制造出多个实例,就会导致许多问题产生。
这里要说的单件模式就能确保一个类只有一个实例,并提供一个全局访问点。
在C++中实现如下:
实现1:
 1 #include <iostream> 2 using namespace std; 3  4 class CSingleton 5 { 6 public: 7   static CSingleton* getInstance(); 8   static void cleanInstance(); 9   int getValue();10   void setValue(int iValue);11 private:12   int m_iValue;13   static CSingleton* m_pSingleton;14   CSingleton();15   ~CSingleton();16 };17 18 CSingleton* CSingleton::m_pSingleton = NULL;19 20 CSingleton::CSingleton()21 {22   cout << "Constructor" << endl;23 }24 25 CSingleton::~CSingleton()26 {27   cout << "Destructor" << endl;28 }29 30 CSingleton* CSingleton::getInstance()31 {32   if (NULL == m_pSingleton)33   {34     m_pSingleton = new CSingleton();35   }36   return m_pSingleton;37 }38 39 void CSingleton::cleanInstance()40 {41   delete m_pSingleton;42 }43 44 int CSingleton::getValue()45 {46   return m_iValue;47 }48 49 void CSingleton::setValue(int iValue)50 {51   m_iValue = iValue;52 }53 54 int main()55 {56   CSingleton* pSingleton1 = CSingleton::getInstance();57   CSingleton* pSingleton2 = CSingleton::getInstance();58   pSingleton1->setValue(123);59   if (pSingleton1->getValue() == pSingleton2->getValue())60   {61     cout << "Two objects is the same instance" << endl;62   }63   else64   {65     cout << "Two objects isn't the same instance" << endl;66   }67 68   CSingleton::cleanInstance();69   return 0;70 }



相信大多数的同仁都喜欢使用上边这种单件模式的实现方法,如果在单线程的情况下,是没有问题的,但如果是多线程,那么就极有可能会返回两个不同的对象,在调用CSingleton::getInstance的时候,两个线程如果都同时运行完if判断,而又还没有调用到构造函数的话,想象下后果吧。那该怎么办呢?看下边这个实现吧。
实现2:
 1 #include <iostream> 2 using namespace std; 3  4 class CSingleton 5 { 6 public: 7   static CSingleton* getInstance(); 8   static void cleanInstance(); 9   int getValue();10   void setValue(int iValue);11 private:12   int m_iValue;13   static CSingleton* m_pSingleton;14   CSingleton();15   ~CSingleton();16 };17 18 // 在进程运行开始就实例化该单件,又称“急切”创建实例19 CSingleton* CSingleton::m_pSingleton = new CSingleton();20 21 CSingleton::CSingleton()22 {23   cout << "Constructor" << endl;24 }25 26 CSingleton::~CSingleton()27 {28   cout << "Destructor" << endl;29 }30 31 CSingleton* CSingleton::getInstance()32 {33   return m_pSingleton;34 }35 36 void CSingleton::cleanInstance()37 {38   delete m_pSingleton;39 }40 41 int CSingleton::getValue()42 {43   return m_iValue;44 }45 46 void CSingleton::setValue(int iValue)47 {48   m_iValue = iValue;49 }50 51 int main()52 {53   CSingleton* pSingleton1 = CSingleton::getInstance();54   CSingleton* pSingleton2 = CSingleton::getInstance();55   pSingleton1->setValue(123);56   if (pSingleton1->getValue() == pSingleton2->getValue())57   {58     cout << "Two objects is the same instance" << endl;59   }60   else61   {62     cout << "Two objects isn't the same instance" << endl;63   }64 65   CSingleton::cleanInstance();66   return 0;67 }


哈哈,看清楚了吗?就是在进程运行的时候就对这个单件进行实例化,可是这样似乎又不能达到延迟实例化的目的啦。如果我们的对象对资源占用非常大,而我们的进行在整个过程中其实并没有用到这个单件,那岂不是白白浪费资源了嘛。还有更好的办法。
实现3:
 1 #include <iostream> 2 using namespace std; 3  4 class CSingleton 5 { 6 public: 7   static CSingleton* getInstance(); 8   int getValue(); 9   void setValue(int iValue);10 private:11   int m_iValue;12   CSingleton();13   ~CSingleton();14 };15 16 CSingleton::CSingleton()17 {18   cout << "Constructor" << endl;19 }20 21 CSingleton::~CSingleton()22 {23   cout << "Destructor" << endl;24 }25 26 CSingleton* CSingleton::getInstance()27 {28   static CSingleton single;29   return &single;30 }31 32 int CSingleton::getValue()33 {34   return m_iValue;35 }36 37 void CSingleton::setValue(int iValue)38 {39   m_iValue = iValue;40 }41 42 int main()43 {44   cout << "Process begin" << endl;45   CSingleton* pSingleton1 = CSingleton::getInstance();46   CSingleton* pSingleton2 = CSingleton::getInstance();47   pSingleton1->setValue(123);48   if (pSingleton1->getValue() == pSingleton2->getValue())49   {50     cout << "Two objects is the same instance" << endl;51   }52   else53   {54     cout << "Two objects isn't the same instance" << endl;55   }56   return 0;57 }


看下运行结果吧:

Process begin
Constructor
Two objects is the same instance
Destructor



是不是跟预想的一样呢?把单件声明为成员函数中的静态成员,这样既可以达到延迟实例化的目的,又能达到线程安全的目的,而且看结果的最后,是不是在程序退出的时候,还自动的调用了析构函数呢?这样我们就可以把资源的释放放到析构函数里边,等到程序退出的时候,进程会自动释放这些静态成员的。