意图
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
定义一个类,这个类有且只有一个可以随时访问的实例。这里需要注意的是【保证】这两个字。
动机
对一些类来说,只有一个实例是很重要的。
确实如此。
虽然系统中可以有许多打印机,但却只应该有一个打印假脱机(printer spooler),只应该有一个文件系统和一个窗口管理器。一个数字滤波器只能有一个A / D转换器。一个会计系统只能专用于一个公司。
先说点闲话,打印假脱机这个翻译没有做到顾名思义,不大好理解。简单地说,print spooler的功能首先是接收应用程序发出的打印指示并存储,然受再通过通讯(并口,串口,USB,网络等)手段发送给打印机。从这个角度来讲,【后台打印服务】这个译法似乎更好些。
《设计模式》中举这个例子因该是想说明后台打印服务只能有一个实例,不同应用都是通过这个实例来访问打印机,这没有问题。同样的道理,一个操作系统中只有一个文件管理器,一个窗口管理器也比较好理解。
但是接下来的例子就有疑问了:
一个数字滤波器真的只能有一个A/D转换器么?如果是一个双声道滤波器呢?
一个公司有一个会计系统么?如果是一个跨国公司呢?
有一个最近流行起来的词叫做细思极恐,细想起来很多所谓的唯一性并不是那么靠谱的。
我们怎么样才能保证一个类只有一个实例并且这个实例易于被访问呢?一个全局变量使得一个对象可以被访问,但它不能防止你实例化多个对象。
前面说过【保证】这个表现很重要。全局变量保证不了唯一性。那怎么办?是编码规范么?当然不是。
一个更好的办法是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建(通过截取创建新对象的请求),并且它可以提供一个访问该实例的方法。这就是Singleton模式。
答案是在提供接口来实现随时随地访问的同时,通过类的内部设计保证该类有且只有一个实例。
作者一句话
单件模式的结构简单,算是最容易理解和使用的一个设计模式。但是在很多情况下,程序员急于利用随时可以访问的这个优点而没有认真判断该类的实例是否真的具有唯一性。
很遗憾,作者看过太多的这种错误。
注:
本文中
蓝 {MOD}粗体文字都引自《设计模式》一书。
由于编排系列号疏忽,Aha34空缺
觉得本文有帮助?请分享给更多人。
阅读更多更新文章,请扫描下面二维码,关注微信公众号【面向对象思考】