码迷,mamicode.com
首页 > 编程语言 > 详细

C++设计模式之——单例模式

时间:2015-04-21 22:10:57      阅读:242      评论:0      收藏:0      [点我收藏+]

标签:

单例模式的概念:

    在GOF的《设计模式:可复用面向对象软件的基础》中是这样说的:保证一个类只有一个实例,并提供一个访问它的全局访问点。首先,需要保证一个类只有一个实例;在类中,要构造一个实例,就必须调用类的构造函数,如此,为了防止在外部调用类的构造函数而构造实例,需要将构造函数的访问权限标记为protected或private;最后,需要提供要给全局访问点,就需要在类中定义一个static函数,返回在类内部唯一构造的实例。

    显然单例模式的要点有三个;一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。
    从具体实现角度来说,就是以下三点:
    一、单例模式的类只提供私有的构造函数;
    二、类定义中含有一个该类的静态私有对象;
    三、该类提供了一个静态的公有的函数用于创建或获取它本身的静态私有对象。
                                                         技术分享
                                                      图示:UML效果展示
代码实现一:(不考虑任何情况,简单实现)
 1 #include <iostream>
 2 using namespace  std;
 3 class Singleton
 4 {
 5 public:
 6     static Singleton* GetInstance();
 7     static void DestroyInstance();
 8     void getTest();
 9 private:
10     Singleton(){ m_test = 0; }
11     static Singleton* m_Instance;
12     int m_test;
13 };
14 Singleton* Singleton::GetInstance()
15 {
16     if (m_Instance == NULL)
17     {
18         m_Instance = new Singleton();
19     }
20     return m_Instance;
21 }
22 void Singleton::DestroyInstance()
23 {
24     if (m_Instance != NULL)
25     {
26         delete m_Instance;
27         m_Instance = NULL;
28     }
29 }
30 void Singleton::getTest()
31 {
32     cout << "m_test:"<<m_test << endl;
33 }
34 Singleton* Singleton::m_Instance = NULL;
35 int main() 
36 {
37     Singleton *singletonTest = Singleton::GetInstance();
38     singletonTest->getTest();
Singleton::DestroyInstance();
39 getchar(); 40 return 0; 41 }

可能存在的问题:没有考虑多线程情况,在多线程情况下就有可能创建多个Singleton实例。

代码实现二:(考虑线程保护)
 1 #include <iostream>
 2 using namespace  std;
 3 class Singleton
 4 {
 5 public:
 6     static Singleton* GetInstance();
 7     static void DestroyInstance();
 8     void getTest();
 9 private:
10     Singleton(){ m_test = 0; }
11     static Singleton* m_Instance;
12     int m_test;
13 };
14 Singleton* Singleton::GetInstance()
15 {
16     if (m_Instance == NULL)
17     {
18         if (m_Instance==NULL)
19         {
20             lock(); //注意,此处加锁只是一个表示,具体使用boost或者其他库文件的接口
21             m_Instance = new Singleton();
22             Unlock();//同上
23         }
24     
25     }
26     return m_Instance;
27 }
28 void Singleton::DestroyInstance()
29 {
30     if (m_Instance != NULL)
31     {
32         delete m_Instance;
33         m_Instance = NULL;
34     }
35 }
36 void Singleton::getTest()
37 {
38     cout << "m_test:"<<m_test << endl;
39 }
40 Singleton* Singleton::m_Instance = NULL;
41 int main() 
42 {
43     Singleton *singletonTest = Singleton::GetInstance();
44     singletonTest->getTest();
45 Singleton::DestroyInstance();
46 getchar(); 47 return 0; 48 }

备注:加锁部分代码进行了双重检测,判断条件是否为null,另外资源销毁时不用加锁,因为最后的资源销毁只需要最后使用的线程进行销毁回收即可,要是每个线程都进行销毁的话,会造成资源丢失和画蛇添足。

可能存在的问题:如果进行大数据操作的话,加锁行为就会成为一种瓶颈。

代码实现三:(避免线程加锁瓶颈)

技术分享
 1 #include <iostream>
 2 using namespace  std;
 3 class Singleton
 4 {
 5 public:
 6     static Singleton* GetInstance();
 7     static void DestroyInstance();
 8     void getTest();
 9 private:
10     Singleton(){ m_test = 0; }
11     static const Singleton* m_Instance;
12     int m_test;
13 };
14 Singleton* Singleton::GetInstance()
15 {
16     if (m_Instance == NULL)
17     {
18         if (m_Instance==NULL)
19         {
20             lock(); //注意,此处加锁只是一个表示,具体使用boost或者其他库文件的接口
21             m_Instance = new Singleton();
22             Unlock();//同上
23         }
24     
25     }
26     return const_cast<Singleton*>(m_Instance);
27 }
28 void Singleton::DestroyInstance()
29 {
30     if (m_Instance != NULL)
31     {
32         delete m_Instance;
33         m_Instance = NULL;
34     }
35 }
36 void Singleton::getTest()
37 {
38     cout << "m_test:"<<m_test << endl;
39 }
40 const Singleton* Singleton::m_Instance = new Singleton();
41 int main() 
42 {
43     Singleton *singletonTest = Singleton::GetInstance();
44     singletonTest->getTest();
45     Singleton::DestroyInstance();
46     getchar();
47     return 0;
48 }
View Code

注意:改动的地方有两个,一个是将静态变量m_Instance声明为const并且进行了初始化,这样做的目的是在多线程中避免频繁加锁,节省开支。

但是如果不想进行实例的销毁,可以使用的成员变量不声明为指针,如下

技术分享
 1 #include <iostream>
 2 using namespace  std;
 3 class Singleton
 4 {
 5 public:
 6     static Singleton* GetInstance();
 7     void getTest();
 8 private:
 9     Singleton(){ m_test = 10; }
10     int m_test;
11 };
12 Singleton* Singleton::GetInstance()
13 {
14     static Singleton m_Instance;
15     return &m_Instance;
16 
17 }
18 void Singleton::getTest()
19 {
20     cout << "m_test:"<<m_test << endl;
21 }
22 int main() 
23 {
24     Singleton *singletonTest = Singleton::GetInstance();
25     singletonTest->getTest();
26     getchar();
27     return 0;
28 }
View Code

 番外篇:

实例销毁和内存释放

在类中,有一些文件锁了,文件句柄,数据库连接等等,这些随着程序的关闭而不会立即关闭的资源,必须要在程序关闭前,进行手动释放;

实例如下:

技术分享
 1 #include <iostream>
 2 using namespace  std;
 3 class Singleton
 4 {
 5 public:
 6     static Singleton* GetInstance();
 7     void getTest();
 8 private:
 9     Singleton(){ m_test = 10; }
10     int m_test;
11     static Singleton *m_Instance;
12     class gc
13     {
14     public:
15         ~gc()
16           {
17               cout << "this is a test" << endl;
18               if (m_Instance!=NULL)
19               {
20                   delete m_Instance;
21                   m_Instance = NULL;
22               }
23         }
24     };
25     static gc g;
26 };
27 Singleton* Singleton::GetInstance()
28 {
29     
30     return m_Instance;
31 
32 }
33 void Singleton::getTest()
34 {
35     cout << "m_test:"<<m_test << endl;
36 }
37 Singleton* Singleton::m_Instance = new Singleton();
38 Singleton::gc Singleton::g;
39 int main() 
40 {
41     Singleton *singletonTest = Singleton::GetInstance();
42     singletonTest->getTest();
43     getchar();
44     return 0;
45 }
View Code

在程序运行结束时,系统会调用Singleton的静态成员GC的析构函数,该析构函数会进行资源的释放,而这种资源的释放方式是在程序员“不知道”的情况下进行的,而程序员不用特别的去关心,使用单例模式的代码时,不必关心资源的释放。那么这种实现方式的原理是什么呢?我剖析问题时,喜欢剖析到问题的根上去,绝不糊涂的停留在表面。由于程序在结束的时候,系统会自动析构所有的全局变量,实际上,系统也会析构所有类的静态成员变量,就像这些静态变量是全局变量一样。我们知道,静态变量和全局变量在内存中,都是存储在静态存储区的,所以在析构时,是同等对待的。

由于此处使用了一个内部GC类,而该类的作用就是用来释放资源,而这种使用技巧在C++中是广泛存在的。

 参考博客:http://www.jellythink.com/archives/82#prettyPhoto

 
 

C++设计模式之——单例模式

标签:

原文地址:http://www.cnblogs.com/jingliming/p/4445162.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!