定义:在某些情况下,我们设计中的对象只需要一个,比方说:线程池(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; m_pSingleton = NULL; 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 else 64 { 65 cout << "Two objects isn't the same instance" << endl; 66 } 67 68 CSingleton::cleanInstance(); 69 return 0; 70 }
实现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; m_pSingleton = NULL; 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 else 61 { 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 else 53 { 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
是不是跟预想的一样呢?把单件声明为成员函数中的静态成员,这样既可以达到延迟实例化的目的,又能达到线程安全的目的,而且看结果的最后,是不是在程序退出的时候,还自动的调用了析构函数呢?这样我们就可以把资源的释放放到析构函数里边,等到程序退出的时候,进程会自动释放这些静态成员的。