Singleton 单件模式
2012-03-10 13:10
176 查看
使用单件模式的意图是保证一个类只有一个实例,并提供一个访问它的全局访问点。
将单件定义为全局或静态对象,然后依赖于自动的初始化,并不能完全实现上述意图。虽然可以提供全局访问点,但这是不够的。原因如下:
1)我们不能保证静态对象只有一个实例会被声明。
2)我们可能没有足够信息在静态初始化时实例化每个单件,单件可能需要在程序运行中稍后被计算出来的值。
3)c++没有定义转换单元上全局对象的构造器的调用顺序。这意味着单件之间不存在依赖关系;如果有,那么错误将是不可避免的。
4)使用全局或静态对象的实现方法,使得所有单件无论用到与否都要被创建。
下面看一下,单件模式如何实现本有的意图并解决上面的问题。
单件实例的示例代码:
构造函数是保护的,客户不能自己创建该类的实例,因此只能通过静态成员函数Instance()来获取该类的实例,静态成员变量m_pInstance和静态成员函数保证了只有一个实例会被创建,而且该实例只有在第一次访问的时候被创建。
Singleton模式具有许多优点:
1)对唯一实例的受控访问。Singleton类封装它的唯一实例,可以严格控制客户怎样及何时访问它。
2)缩小命名空间。Singleton模式是对全局变量的一种改进,避免了那些存储唯一实例的全局变量污染命名空间。
3)允许对操作和表示的精华。Singleton类可以有子类,而且用这个扩展类的实例来配置一个应用是很容易的。你可以用所需要的类的实例在运行时刻配置应用。
4)允许可变数目的实例。允许Singleton类的多个实例,可以用相同的方法来控制应用所使用的实例数目,只有允许访问Singleton实例的操作需要改变。
5)比类操作更灵活。
下面考虑多线程情况下的Singleton。
多线程时,在if(m_pInstance == NULL)这句,可能会有多个线程进入,从而导致了多个实例的创建,也造成了内存的泄露。所以应该加上线程间的互斥操作。
多线程单件模式示例代码:
这里用双检查,只有在第一次创建的时候才会去考虑互斥,以提高效率。
上面的代码还有一个问题,m_pInstance所指向的空间什么时候释放呢, 怎么样完成实例的析构操作。如果类析构行为中有关闭文件,释放资源等操作,那么我们的代码必须在合适的时机正常的析构该实例。
下面给出解决该问题的一个方法:
另外还有一种方法,但是该方法处理线程安全问题比较复杂,这里暂不考虑线程安全,只考虑析构问题:
(未考虑线程安全):
Singleton模式是比较简单的一个设计模式,应用也比较多,也常常配合其他设计模式使用。
参考资料:《设计模式-可复用面向对象软件的基础》以网上众多博客
将单件定义为全局或静态对象,然后依赖于自动的初始化,并不能完全实现上述意图。虽然可以提供全局访问点,但这是不够的。原因如下:
1)我们不能保证静态对象只有一个实例会被声明。
2)我们可能没有足够信息在静态初始化时实例化每个单件,单件可能需要在程序运行中稍后被计算出来的值。
3)c++没有定义转换单元上全局对象的构造器的调用顺序。这意味着单件之间不存在依赖关系;如果有,那么错误将是不可避免的。
4)使用全局或静态对象的实现方法,使得所有单件无论用到与否都要被创建。
下面看一下,单件模式如何实现本有的意图并解决上面的问题。
单件实例的示例代码:
class Singleton { public: static Singleton* GetInstance(); protected: Singleton(); private: static Singleton * m_pInstance; }; Singleton * Singleton::m_pInstance = NULL; Singleton * Singleton::GetInstance() { if(m_pInstance == NULL) { m_pInstance = new Singleton; } return m_pInstance; }
构造函数是保护的,客户不能自己创建该类的实例,因此只能通过静态成员函数Instance()来获取该类的实例,静态成员变量m_pInstance和静态成员函数保证了只有一个实例会被创建,而且该实例只有在第一次访问的时候被创建。
Singleton模式具有许多优点:
1)对唯一实例的受控访问。Singleton类封装它的唯一实例,可以严格控制客户怎样及何时访问它。
2)缩小命名空间。Singleton模式是对全局变量的一种改进,避免了那些存储唯一实例的全局变量污染命名空间。
3)允许对操作和表示的精华。Singleton类可以有子类,而且用这个扩展类的实例来配置一个应用是很容易的。你可以用所需要的类的实例在运行时刻配置应用。
4)允许可变数目的实例。允许Singleton类的多个实例,可以用相同的方法来控制应用所使用的实例数目,只有允许访问Singleton实例的操作需要改变。
5)比类操作更灵活。
下面考虑多线程情况下的Singleton。
多线程时,在if(m_pInstance == NULL)这句,可能会有多个线程进入,从而导致了多个实例的创建,也造成了内存的泄露。所以应该加上线程间的互斥操作。
多线程单件模式示例代码:
class Singleton { public: static Singleton* GetInstance(); protected: Singleton(); private: static Singleton * m_pInstance; }; Singleton * Singleton::m_pInstance = NULL; Singleton * Singleton::GetInstance() { if(m_pInstance == NULL) { Lock(); if(m_pInstance == NULL) m_pInstance = new Singleton; Unlock(); } return m_pInstance; }
这里用双检查,只有在第一次创建的时候才会去考虑互斥,以提高效率。
上面的代码还有一个问题,m_pInstance所指向的空间什么时候释放呢, 怎么样完成实例的析构操作。如果类析构行为中有关闭文件,释放资源等操作,那么我们的代码必须在合适的时机正常的析构该实例。
下面给出解决该问题的一个方法:
class Singleton { public: static Singleton* GetInstance(); protected: Singleton(); private: static Singleton * m_pInstance; class Garbo { public: ~Garbo() { delete Singleton::m_pInstance; } }; static Garbo m_garbo; }; Singleton * Singleton::m_pInstance = NULL; Singleton::Garbo Singleton::m_garbo; // 不要忘记此处的定义 Singleton * Singleton::GetInstance() { if(m_pInstance == NULL) { Lock(); if(m_pInstance == NULL) m_pInstance = new Singleton; Unlock(); } return m_pInstance; }上述方法在Singleton内定义了一个私有内嵌类,防止该类在其他地方使用。程序运行结束时,系统会调用Singleton类静态成员的m_garbo的析构函数,该析构函数会释放m_pInstance实例并进行析构操作。
另外还有一种方法,但是该方法处理线程安全问题比较复杂,这里暂不考虑线程安全,只考虑析构问题:
(未考虑线程安全):
class Singleton { public: static Singleton* GetInstance(); protected: Singleton(); }; Singleton * Singleton::GetInstance() { static Singleton instance; return &instance; }这种方法仅在第一次调用GetInstance时初始化该类,在程序结束时自动析构。代码简短,是一种有效的方法。不过,不管是否用到该类,都要为该类分配空间,但是满足在必要的时候才执行初始化操作。
Singleton模式是比较简单的一个设计模式,应用也比较多,也常常配合其他设计模式使用。
参考资料:《设计模式-可复用面向对象软件的基础》以网上众多博客
相关文章推荐
- 实战设计模式系列-Singleton(单件)
- 面向对象设计模式学习(二):Singleton单件创建型模式
- Python和Singleton (单件)模式[转载]
- 【设计模式】学习笔记7:单件模式(Singleton)
- 单实例模式的实现(singleton)----单件
- 单件模式(Singleton)
- C++设计模式之五:SINGLETON(单件模式)
- 创建型模式-单件(Singleton)
- 单件模式 The Singleton Pattern
- 我的设计模式之旅(2)――单件模式Singleton
- Ogre不负责任研究(二)单件模式的运用,Ogre::Singleton
- C++设计模式之Singleton(单件/单例)模式
- ISingletonDisplayer 单件模式显示器C#实现
- 设计模式学习笔记:Singleton(单件模式)
- (创建型模式)Singleton 单件模式
- C#面向对象设计模式纵横谈(Singleton单件)
- 创建型模式——Singleton 单件模式
- <Head First 设计模式>:单件模式:Singleton
- Singleton单件模式的思考
- 基于私有化构造器与析构器的单件模式(singleton) 实现及注释