杂谈Singleton模式,Monostate以及DCL

原创 2008年08月05日 13:27:00

杂谈Singleton模式,Monostate以及DCL

[目录]
一句话简介Singleton
局限性
实现手法
优缺点和问题
MonoState vs Singleton
Mutithreading: ACE中的DCL
DCL的应用条件

[前面的一陀]

(明明目录中没有,但还是想写,看来但凡写点文章或者翻译些文章的人,都会想到要搞一陀?)

Singleton可是面试时的老朋友了——平均每个月都会有那么几次
有些面试题上面写着:Apart from Singleton, descirbe a Design Pattern below —— 英语不好的达淫可能要吃亏了
有些应试者在被问到Design Pattern的时候,憋了半天也只能说出一个Singleton —— 于是面瓜(官)们面露邪恶地微笑,满心欢喜道:早就料到你小子不行,哼哼
……

扯点稍远的话题,其实Design Pattern也就是在C风格的语言中显得如此地必要、如此地“经典”、如此地“神圣”……甚至于有了Design Pattern的metaphysics:
——只要你使用了Design Pattern,你就可以做得很好;
——而你做得不够好,是因为你没有使用Design Pattern!
(大家可以联想一下戈培尔的“元首版”)

(计算机编程语言只有2种风格,一种是C语言风格,另一种是LISP风格,像Java语言如此之成功,无外乎是在C风格的基础上向LISP借鉴了一些“智能”因素,这也是近些年来语言设计的万灵大法和花葵红宝典,比如Garbage Collection/ Mix-in/ Closure/ AMB/ Continuation ... etc etc etc)

设计模式在C++/Java语言和社区中很有地位,但是在LISP/SCHEME等语言中,Design Pattern就是一陀陀碍眼的米田共。不信,你可以试着写一个Double-Dispatching Visitor,再看看LISP中的multimethod功能(定义generic function)有多么强大,最后再决定是不是要用C++/Java这样的旧石器时代的工具打造一个Triple-Dispatching Visitor。附带说一句,连JavaScript都把Generic Function添加到ECMA标准中了。

——如果以上的话语深深地伤害了无辜的PLoP fans和模式社区,请将矛头对准Peter Norvig的这个Slide(http://norvig.com/design-patterns/)。
这位名叫Peter Norvig的老大你肯定听说过
——如果没听说过,那你肯定看过《十年编程无师自通》那篇文章
——如果你连那篇文章也没看过,那请按一下键盘上的Alt键,然后按空格键,再按字母C。
P.S. 另一个例子是Observer和Before/After

[一句话简介Singleton]
终于可以开始本文的正题了。
Singleton是一种惯用写法,它让你可以通过一个小辨子将幕后的大BOSS揪出来。

[局限性]
既然它只是一种惯用写法,那么它能带来的好处也就不会太多,顶多和其它“写法”带来的好处一样多。这方面典型的例子是误以为Singleton会跨进程、跨线程起作用,比如用它禁止多实例启动。
Singleton的实现和使用上也是有比较多的麻烦,比如:
A) 书写方便性问题:每个需要singleton的类型都需要单独书写名为singleton的一陀
B) 模板编译问题:如果为了解决书写方便性问题,使用了模板进行辅助(比如使用LOKI: http://sourceforge.net/projects/loki-lib/ ),那么,偶尔碰上编译器生成了singleton的多份内存实例会头痛得要死(一般仅仅在release时发生)
C) 实例化顺序问题:要维护和保证50个singleton对象的产生和释放按要求的顺序进行,可不是一件容易的事情。
D) 又臭又长的程序行:如果一个函数调用,以及它的若干参数都是通过singleton来取得的,那这一行肯定丑陋不堪。作为一个合格的程序员绝不能坐视这种问题。
Sorry,上面的几条俺自己也有点看不下去。归根结底是因为俺实再是不习惯列举1234这样的条目。初中时背政治题,左一条右一条的那种列举题俺一向是不在行。脑子里想如果答题时也有car/cdr那该多么好呀多么好……

[实现手法]
暂略,寻找面筋的可以离开这个页面了。(当然,你要是将上面的一大段侃给面瓜听效果也会不错,关键看你能不能争取得到很多自由发言的时间)

[优缺点和问题]
优点不提,缺点也懒得再说——这个目录编得比较失败的说。

[MonoState vs Singleton]
终于来了点提神的,可以说点“不为人知的秘密”(80年代飘柔广告语,估计会有人想起那一群空姐窃窃私语然后笑靥如花的画面)
Singleton的写法在某些情况下显得又臭又长,怎么解决?作为编程问题,往往是答案早已摆在某处,所以多数程序员都喜欢用google之类的东西去“复用”一下。PLoP的达人们可以忽略本节了,俺是在看了BOB大叔的书(http://www.objectmentor.com/omTeam/martin_r.html)之后才知道有这个模式的。

先看看这一行:
PrinterService::getPrinter().Print(PrinterConfigService::getPrinterConfig(), "How long gone are you gonna be/ Brooks & Dunn, 1998/n");
上面这一行是Singleton牌的,OEM来自王母娘娘。

再来看这一段:
PrinterService printer;
PrinterConfigService config;
printer.Print(config, "Born & Raised in Black & White/ Brooks & Dunn, 1998/n");
上面的来自于MonoState。

其实只是写法不同,背后的操作策略都是一样的。MonoState这个名字本来的意义就是指,同一个类型,但是所有不同的对象共享同样的“单一状态”。
MonoState更符合人的思路,也更符合人们的习惯。实际上,打印机这东西,很少有人按Singleton去写的,多数是MonoState

(至于为什么“隐藏在背后的操作都一样”,我偏偏不说,天知,地知,我知,还有小坏狗知……)

[Mutithreading: ACE中的DCL]
如果我不写什么是DCL,只给出Douglas c. Schmidt的这个文章的链接,会不会有鸡蛋扔上来呢?先试试,没有反对的我就这么着,可以省事儿了——反正看我BLOG(http://blog.csdn.net/yuankaining)的人估计不会太多。
道格拉斯童鞋的文章在这里:http://ftp.icm.edu.pl/packages/ace/ACE/PDF/DC-Locking.pdf
<未完待插>

[DCL的应用条件]
DCL在Java中无效。C++的粉丝们可以大笑了。Anyway, anyhow, yet another shortcoming of Java.
可是,等一下,为什么?为什么这个在逻辑上行得通的DCL,这个任何程序员都可以人肉演算的程序片段,在Java中就不行?难道Java违背了社会的普遍真理,抛弃了辩证唯物主义和历史唯物主义,走到了反人类的歧路上?
每一个编译优化都是痛苦艰辛而且不讨好的。说它“痛苦艰辛”,是因为“编译器的效能每18年翻上一倍”(这个叫做Proebsting's Law,参见http://research.microsoft.com/~toddpro/)。说它“不讨好”,是因为编译器优化常常“好心干坏事”,自作聪明地为了性能牺牲质量(萝卜快了不洗泥之计算机版?)。

为什么要讨论DCL的失效呢?(像这样的问句,在这种文章里都会有一个答案。这种修辞手法叫做设问,也就是自问自答——“问”是为了“答”;“答”是回应“问”。说白了就是“吃多了撑的、装着明白犯糊涂”)其实,我是想要引出一个很邪恶很强大的东东,这个东西叫做CAS。

但是在说CAS之前,我还得要先说点别的东东。(这在说书的时候叫“花开两朵、各表一枝”,也可以叫“卖关子”)
——如果你写过exception-safe的程序,你肯定知道有一个手法——Bingo! 但是你猜错了,不是RAII,而是ABR Idiom。ABR是Acquisition Before Release,也就是说先把新的资源搞定了,然后用一个no-exception guarantee的swap将新老资源的进行交换(例如:C++中的指针交换或者STL container的swap函数),然后对老资源进行释放,这个是针对Strong Exception-Safe Guarantee的常用手法(参考一下这里:http://www.accu-usa.org/2001-03-Main.html)。

写点代(伪)码来表达一下上述的东西:
// The following lines guarantee Strong Exception Safety
extern Vector oldVal;
Vector newVal = new Vector(oldVal); // Acquisition
newVal.push_back(Element("param")); // Push a new element into the vector
oldVal.swap(newVal); // No exception will be thrown from this function
// The destructor of newVal will release elements prior in oldVal
如果你能体会得到这种思路的优越性,那么恭喜你,你已经悟道了。

现在,我们回过头来说CAS(http://www.ddj.com/cpp/184401865)。CAS是Generic<Programming>专栏的Andrei Alexandrescu小盆友发明的东东,作为专栏作者,Andrei童鞋是有权发明新的缩写的,这个CAS就是Compare And Swap的缩写。下面的伪码(注意不是代码)来自于Andrei的文章:
template <class T>
bool CAS(T* addr, T expected, T value) {
   if (*addr == expected) {
      *addr = value;
      return true;
   }
   return false;
}

需要再次强调的是,上面的几行是“伪码”。因为这个函数是用来“示意”的,实际上这是一个原子操作——这的的确确是如假保换,即使是多CPU也不会打破的原子操作(手持Alpha射线枪的、卢瑟福之类的小人闪到一边去!!!)。Andrei从Intel处理器中挖出了一条叫CMPXCHG8的汇编指令说可以实现这种操作,不过汇编这东东我还是不在行,说多了献丑。于是就此打住。好了,现在全文终,大家可以洗洗睡了……

嗯,以上一句作废。接下来想说的是:用这个CAS原子操作可以解决DCL问题。

<未完待插>
 
[结论]
由上可见,多简单的东西都可以拿来侃。Over.

[关于作者]
Kenny Yuan,从1990年开始学习编程。目前对算法,语言,心理学和综合格斗感兴趣。

[声明]
本文写于2008年8月,文中涉及的技术性内容随时间变化可能会有变化(特别是某些观点、技术限制等)。

[zt] 杂谈Singleton模式,Monostate以及DCL 收藏

 http://blog.csdn.net/yuankaining/archive/2008/08/05/2770430.aspx  杂谈Singleton模式,Monostate以及DCL ...
  • remox
  • remox
  • 2009-11-05 22:52:00
  • 316

设计模式(二):MonoState模式

MonoState模式:先说说MonoState这个单词的意思,设计模式的名字都是很有意思的,因为为了方便交流、记忆,所以设计模式的命名都对该模式的意图进行了表述。Mono是一个词根,英语中Mono,...
  • nirvana_li
  • nirvana_li
  • 2006-12-19 16:42:00
  • 4325

Singleton 与 MonoState 模式

原文地址:http://www.cnblogs.com/youzai/archive/2007/12/24/1013103.html 1. Singleton 模式的不同实现形式  1) 最简单的Si...
  • lhlaugh
  • lhlaugh
  • 2008-12-12 14:16:00
  • 1116

单例模式(DCL缺陷以及如何安全发布对象)

1. 单例模式:
  • u014108122
  • u014108122
  • 2014-08-02 21:45:59
  • 1938

SINGLETON 模式和MONOSTATE 模式

Singleton 和 Monostate 都是用来实现单例模式的,但二者实现机制上有所不同。Singleton 模式使用私有构造函数,一个静态变量以及一个静态方法对实例化进行控制和限制;而Monos...
  • salever
  • salever
  • 2010-03-11 19:24:00
  • 302

java设计模式学习系列之一:单例模式(Singleton)

单例模式(Singleton)    1.介绍:也叫单子模式,是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们...
  • qjyong
  • qjyong
  • 2007-08-01 17:09:00
  • 22012

单例模式、双检测锁定DCL、volatile

单例模式最要关心的则是对象创建的次数以及何时被创建。 Singleton模式可以是很简单的,它的全部只需要一个类就可以完成(看看这章可怜的UML图)。但是如果在“对象创建的次数以及何时被创建”这两点上...
  • licong20060541
  • licong20060541
  • 2015-09-25 22:37:47
  • 1060

双重检查模式 (DCL)与单例模式

今天浏览CSDN博客无意间浏览到这篇文章,感觉受教了,原文已经很详尽,为怕日后忘记,特意转载,请原作者勿怪! 原链接地址:http://blog.csdn.net/zhangzeyuaaa/artic...
  • sinat_15891495
  • sinat_15891495
  • 2017-10-11 22:33:04
  • 83

JAVA设计模式-单例模式(Singleton)的五种实现方式

单例(Singleton)模式 也叫单态模式 我在另一篇文章中已经介绍过了过关于单例模式的简单描述和优缺点,感兴趣的朋友可以点击下面的连接,在这里我就不在赘述。 单例模式(Singleton)应用...
  • Mr_PH
  • Mr_PH
  • 2017-10-10 14:42:02
  • 105

Python实现Singleton模式

Singleton模式即单例对象必须必须保证只有一个实例存在。可以说Singleton是设计模式中最基本一种设计模式,在学习设计模式时一般都会先了解该模式。在Python中实现单例模式有很多方法,下面...
  • lqxqust
  • lqxqust
  • 2016-07-14 16:49:18
  • 557
收藏助手
不良信息举报
您举报文章:杂谈Singleton模式,Monostate以及DCL
举报原因:
原因补充:

(最多只允许输入30个字)