【设计模式攻略】创建型模式之Singleton模式(也谈勿滥用Singleton)

概要
如果要说GOF提出的设计模式中最简单以及用的最多的模式是哪种,无疑应该是Singleton模式。它的实现仅仅涉及一个Class,由这个类来负责其本身的实例化,而这个实例化满足唯一性的要求就可以,就这么简单。但是,正因为其简单,简单到随手可用,导致Singleton模式又是目前最容易被滥用的一种模式。后文会讨论滥用Singleton会带来什么问题。

目的
确保仅仅会实例化一个唯一的对象,并且提供一个全局的方法来访问该对象及其成员。

实例
先来看Singleton的实现,简单之极,一个类,一个static成员,一个private构造函数,一个static public的方法就可以实现Singleton,代码如下:
Class Singleton {
public:
     static Singleton* get_instance() {
          if (_instance == NULL) {
               _instance = new Singleton;
          }
          return _instance;
     } 
     // anything you want to be implemented
     void do_something() {}
private:
     Singleton() {}
     static Singleton* _instance;
};
private构造函数是防止通过new来实例化对象,get_instance方法是最为全局方法来访问Singleton对象。使用方则不再需要考虑如何实例化对象,如何传递对象,如何调用,直接获得instance就可以:
Singleton::get_instance()->do_something();

应用
开始就说过,Singleton模式是使用最广泛的模式之一,比如在Logger机制,Factory类的实现等等中对Singleton的使用都比较常见,
既然Singleton如此简单,那为何又说Singleton模式是被滥用最多的模式呢?
首先讨论下到底什么时候应该使用Singleton? 众所周知的是,当需要唯一性的实例对象时,可以考虑使用Singleton。但这其实只是个必要条件,我们不妨来分析以下这些问题:
1. 并发与线程安全
虽然Singleton本身是线程安全的,但Singleton对象的实现却是依赖于具体功能,并非绝对线程安全,比如上面的do_something方法的实现。当在多线程中同时使用Singleton对象来调用时,就必须考虑同步保护,而同步保护必然带来额外的开销,当在你的程序中,使用传统new的实例化多对象可以解决线程安全问题时,那或许你就需要考虑下再使用Singleton是否还合适?
2. 对象生命周期
一个对象完整的生命周期要包含创建到应用到销毁,而Singleton模式的传统实现其实淡化了对象销毁的过程,那么当你的程序需要兼顾对象完整的生命周期时,使用Singleton就带来了一定问题。举个常见的问题,有的项目滥用Singleton后带来的直接问题是,发现代码的Unit testing无法进行,原因是什么?Unit testing强调每个test case都是独立的过程,不受其他test case的影响,这意味着每个test case需要管理从对象的生成到销毁,保证下个test case又是一个全新的开始,而Singeton则因为无法销毁对象,会把当前test case运行后对Singleton对象状态的改变的带到下一个test case。这种情况下,你又需要考虑下,到底哪些应该用Singleton,哪些不合适用Sington?
3. OOD
Singleton一定程度上会破坏面向对象设计。有人或许会说,Singleton就是从OO的角度提出的设计模式,为什么会说Singleton会破坏OOD呢?其实我们仔细考虑下Singleton的使用方式,通过全局方法获得instance,然后直接调用相关方法,这种方式跟什么类似?跟C风格的全局函数类似!所以很多人图方便,滥用Singleton使得代码中从上至下充斥这各种Singleton对象,进而回归到面向过程的思考方式,完全没有从OO的角度去考虑设计。其实我的习惯是只有对最外层的类(暴露接口给外部使用),同时该类又确定具有唯一性时才考虑是否使用Singleton,而对内部处理则是尽量少用或不用,因为Singleton会割裂类与类之间的关系,同时又会妨碍Unit testing的进行。
4. 唯一性
在使用Singleton时,请反复问自己,该对象是不是过去,现在,以及未来都确定只会是唯一的。因为如果现在使用Singleton,给以后对支持多实例的带来很多麻烦。
现在你还会滥用Singleton吗?Singleton模式本身没有问题,只是希望我们的使用不要出问题。


【设计模式攻略】创建型模式之Singleton模式(也谈勿滥用Singleton)

上一篇:mac系统用键盘操作菜单栏


下一篇:PetShop4.0(一)