深一层看Singleton

转载自:Todd Wei

http://www.cnblogs.com/weidagang2046/archive/2009/10/31/1593473.html

Singleton模式通常被认为是比较容易理解和运用的设计模式。目前,网上已经有相当多的资料讲解Singleton的基础知识,本文试图避免重复性的介绍,而是尝试从不同的角度更深入地探讨Singleton。

“保证对象有唯一的实例,并且提供一个全局访问点”是Singleton模式比较常见的描述。不知您是否意识到,这个定义本身就散发着某种"bad smell"。为什么要把“保证对象有唯一实例”的创建职责,和“提供一个全局访问点”的访问职责混入一个模式呢?

为了更清楚地说明这个问题,我们假设有一个Singleton的类A,并通过静态方法A.Instance()提供唯一实例。使用者类B通常会直接以A.Intance().Do()的方式来使用它(因为这样很方便)。这里我们需要追问的是B的设计,“B一定要A的单例对象才行吗?不是单例可以吗?”。其实,绝大多数情况B所需要的仅仅是A的对象,它甚至根本不需要知道“单例”为何物。但不幸的是以方便的理由,“单例”成功地混入了B,这就造成B对A的“单例耦合”。"单例耦合"直接损害了B的可测试性,因为我们无法对类A进行mock,只能带着A测试B,扩大了测试边界。一般来讲,具有好的可测试性的模块,通常表现为依赖注入的开放式设计,因为这样才方便通过mock等方式模拟外部依赖,让测试专注于模块本身的逻辑,即测试边界只包含被测模块本身。

通过上面的分析,问题已经很清楚了,B是A的使用者,它只关注A提供的功能接口;A只能有唯一实例是A的创建者的事情,与B无关。所以,我们提倡B应该采用开放式的依赖注入,比如通过构造函数或者通过Setter让外部注入A的实例,不要仅仅因为方便而滥用Singleton。对于创建唯一实例的职责可以采用传统Singleton模式,也可以采用其它方式。从理论上讲,创建A的职责不一定要放在A内部来实现,我们完全可以结合工厂模式,设计所谓的单例工厂,保证从这个工厂出品的对象是唯一实例。

其实,某些情况下,我们的真实需求并非“保证类有唯一对象”而是“保证类对象有唯一的状态”。这里涉及两个问题:

第一“既然是类,又是唯一,为什么不干脆弄成static算了,还要Singleton模式干嘛?”。其实,这是为了避免使用者B对类A的直接依赖,采用static就无法把B设计成依赖注入式的,采用static意味着失去了多态。这里的多态特别指对Singleton类本身有接口要求,那么static设计就直接被排除在外了。

第二“既然用户不关心是一个对象还是多个对象,是否可能类有多个对象,但都共享同一状态,用这种方式实现状态唯一性需求?”。答案是肯定的,MonoState模式正是采用这种方式,把唯一状态通过static成员封装在类内部,让所有对象共享同一状态。与Singleton相比,MonoState更好地分离了状态唯一性和对象使用,避免出现耦合。

更多关于Singleton模式的探讨,可以参考:

1. Patterns I Hate #1: Singleton

2. Why Singletons are Evil

时间: 2024-10-13 16:12:46

深一层看Singleton的相关文章

看得“深”、看得“清” —— 深度学习在图像超清化的应用

日复一日的人像临摹练习使得画家能够仅凭几个关键特征画出完整的人脸.同样地,我们希望机器能够通过低清图像有限的图像信息,推断出图像对应的高清细节,这就需要算法能够像画家一样"理解"图像内容.至此,传统的规则算法不堪重负,新兴的深度学习照耀着图像超清化的星空. 本文首发于<程序员>杂志 图1. 最新的Pixel递归网络在图像超清化上的应用.左图为低清图像,右图为其对应的高清图像,中间为算法生成结果.这是4倍超清问题,即将边长扩大为原来的4倍. 得益于硬件的迅猛发展,短短几年间,

云南看云

云南看云云南是因云而得名的,可是外省人到了云南一年半载后,一定会和本地人差不多,对于云南的云,除了只能从它变化上得到一点晴雨知识,就再也不会单纯的来欣赏它的美丽了.看过卢锡麟先生的摄影后,必有许多人方俨然重新觉醒,明白自己是生在云南,或住在云南.云南特点之一,就是天上的云变化得出奇.尤其是傍晚时候,云的颜色,云的形状,云的风度,实在动人.战争给了许多人一种有关生活的教育,[url=http://yboss.cn/]河南癫痫病医院地址[/url]走了许多路,过了许多桥,睡了许多床,此外还必然吃了许

Smarty前端模板引擎 - 我看过的PHP开源框架

Smarty Smarty可以说是我接触PHP这门语言用到的第一个开源框架,当时在Smarty的帮助下,很好地完成了项目的开发,也很好地遵循了MVC的模式.但是到了后来,慢慢地发现,很多人都很熟悉Smarty,但是都不愿意使用它.大概的原因在于:慢. 当初以为Smarty很神奇,到后来发现也是通过PHP来实现的.再到后来别人反映使用Smarty会影响性能,所以也就想深入了解一下它的源代码,看下它是怎么实现的,是不是真的会慢? 其实,Smarty只是用PHP做了一个中间层,来把自定义的一些模板标签

《用户体验要素》澄清了 UI 原型设计中看不见确感受得到的那一层

<用户体验要素>澄清了看不见确感受得到的那一层 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. <在熟练使用2B铅笔前,请不要打开Axure>一文中精要部分摘录如下,并

Asp.Net实现FORM认证的一些使用技巧(必看篇)

最近因为项目代码重构需要重新整理用户登录和权限控制的部分,现有的代码大体是参照了.NET的FORM认证,并结合了PORTAL KITS的登录控制,代码比较啰嗦,可维护性比较差.于是有了以下的几个需求(大多数系统应该都会碰到): 1.用.NET自带的FORM认证来实现安全登录 2.登录后需要记录登录用户的基本信息,方便所有页面调用 3.记录本机登录状态,短时间关闭窗口后不用重新登录 4.权限控制和代码的文件夹结构相呼应,即按角色允许访问不同的目录 5.权限控制有可能需要细化到每一个页面,即按角色允

看了一篇出现过无数次英语学习方法论-新感悟

学英语一路考试到现在需要实际运用到工作,觉得过程中最重要的是"模仿,比较,区别,模仿”,无论是预习-复习-听课-作业还是听说读写自我训练每一个过程都离不开这个过程!找自己的方法是模仿带入了这样的过程后,你玩英语,而不是英语玩你!^_^?•??•??•??•??•??•?•??•? -----------------(????)╭ - ?我是原文----------- 在21世纪的社会里,英语是一门不可缺少的课程,如果不懂英语,就会被人视为落后,也会被社会淘汰,所以,作为21世纪的新一代,我们必须

HDU1572-下沙小面的(2)-最短路(深搜)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1572 好吧,没想到这题用深搜可以搞定.还以为又是一道套dijkstra算法的模板题. #include<iostream> #include<string> #include<cstdio> #include<cstring> #include<map> #include<queue> #include<cmath> #inc

创业半年总结出的这3点,老板看了也点赞

周一给大家醒醒脑,说不定这一周就能多做点事,比如多刷一集十二时辰-- 故事是这样子的,上周周一到周六一直在客户那里,天天从早上6点肝到晚上11点.12点,是不是贼辛苦啊?是不是觉得我特拼特努力啊? 错!大错特错!了解我的读者都知道我有时候喜欢给大家讲讲鸡汤,给大家讲讲努力的道理,但偏偏今天我要换个思路. 因为这么一周做下来,并没有被那么努力的我感动,反倒是有些担忧.有几件事情,我给大家一一说来. 0. 大背景就是我现在创业,做数据中台,负责售前.售后.方案架构.技术支持,除了不写业务代码啥都做.

23种设计模式介绍以及在Java中的实现

原创不易,转载请注明出处:http://anxpp.com/,谢谢!     文章比较长,读者可以通过顶端的目录选择要了解的模式,然后通过文章右边的按钮快速返回顶部重新选择一个新的模式浏览 博主精心准备了大量的示例代码.文章尽量提供与编程相关的例子,而不是像多数其他介绍的文章一样,提供一些感觉挺滑稽的例子(那样的例子可能看完觉得写得很好,然而还是不会用...). 本文耗费了作者大量时间,还请亲们给个赞O(∩_∩)O~ 也可以通过CTRL+F并输入要了解的模式并跳到对应位置. 文章中的示例源码在g