2008-02-23
singleton迷恋
关键字: singleton
自从知道singleton模式这把锤子是什么样的之后,我就把很多小疙瘩也当成了钉子,时常想象偶顶着模式的光环挥舞着“万能”锤子在代码丛林中学习兰
博搏斗的光辉形象~~~~。昨天读《重构与模式》的inline
singleton一节,一句话点醒梦中人,singleton模式是“保证一个类仅有一个实例,并提供一个访问它的全局访问点”,原来——
singleton也是全局变量啊。马教主深刻地教育过我们:全局变量在被证明无害之前都是有害。偶大汗淋漓。看看迷恋singleton的几种现象:
1、仅仅在一个地方调用到了某个singleton实例,并且对这个实例的处理代码也集中在这么一两个地方,这样的情况下你为什么要singleton?这里需要一个个全局访问点吗?我看你是为了singleton而singleton。
2、我为了性能优化啊!singleton只有一个实例,减小了创建开销。oh,我终于找到一个用singleton的充分理由了——性能。慢着,跟我读高大师的名言:“不成熟的优化是万恶之源”。 你怎么知道singleton对象的重复创建是明显影响了性能?现代jvm对“短命”对象的创建代价已经非常低了。不成熟的优化不仅可能是无效的,而且也 给以后重构工作带来了困难。除非有明显数据证明(分析工具而来)某个对象的重复创建是对性能影响极大,否则所谓性能优化不能成为采用singleton模 式的理由。
3、有时候我们需要在系统的不同层次间传递一些共享信息,如果不采用singleton对象来提供这些共享信息,就得在调用的方法中重复地传递这些参数, 这是个应用singleton模式的场景。但是,如果这些共享信息是可被修改的,或者说singleton对象不是无状态的,如果还采用 singleton模式,那么你就不得不在调用的方法中从single对象取出旧信息和存入新信息,这样的重复代码将遍布的到处都是,不仅仅引入了同步访 问的需要,而且出错的风险大大提高。这种情况下你还将这些信息作为方法参数传递而不是采用singleton可能更为清晰和健壮。
singleton不仅仅是“保证一个类仅有一个实例”(这仅仅是描述),更重要的是它是用来“提供全局访问点”的(这才是它的功能),不要再迷恋这把锤子,好好利用这把锤子。
题外话:脚本语言似乎更容易滥用全局变量,javascript里可以模拟命名空间,Ruby也可以模拟类似的机制。最近写的一个比较大一点的Ruby脚 本,用了几个全局变量(都是数组)用于保存状态数据,一开始没有意识到这一点,导致对全局变量的访问散落在好几个脚本文件里,RDT下看起来红通通的一片 极其不爽。那么就重构吧——封装数组重构,将对这些全局数组的访问和修改操作统一到一个模块,调用全局变量的地方都引用这个模块,通过模块去操作全局变 量,代码看起来清爽多了。
1、仅仅在一个地方调用到了某个singleton实例,并且对这个实例的处理代码也集中在这么一两个地方,这样的情况下你为什么要singleton?这里需要一个个全局访问点吗?我看你是为了singleton而singleton。
2、我为了性能优化啊!singleton只有一个实例,减小了创建开销。oh,我终于找到一个用singleton的充分理由了——性能。慢着,跟我读高大师的名言:“不成熟的优化是万恶之源”。 你怎么知道singleton对象的重复创建是明显影响了性能?现代jvm对“短命”对象的创建代价已经非常低了。不成熟的优化不仅可能是无效的,而且也 给以后重构工作带来了困难。除非有明显数据证明(分析工具而来)某个对象的重复创建是对性能影响极大,否则所谓性能优化不能成为采用singleton模 式的理由。
3、有时候我们需要在系统的不同层次间传递一些共享信息,如果不采用singleton对象来提供这些共享信息,就得在调用的方法中重复地传递这些参数, 这是个应用singleton模式的场景。但是,如果这些共享信息是可被修改的,或者说singleton对象不是无状态的,如果还采用 singleton模式,那么你就不得不在调用的方法中从single对象取出旧信息和存入新信息,这样的重复代码将遍布的到处都是,不仅仅引入了同步访 问的需要,而且出错的风险大大提高。这种情况下你还将这些信息作为方法参数传递而不是采用singleton可能更为清晰和健壮。
singleton不仅仅是“保证一个类仅有一个实例”(这仅仅是描述),更重要的是它是用来“提供全局访问点”的(这才是它的功能),不要再迷恋这把锤子,好好利用这把锤子。
题外话:脚本语言似乎更容易滥用全局变量,javascript里可以模拟命名空间,Ruby也可以模拟类似的机制。最近写的一个比较大一点的Ruby脚 本,用了几个全局变量(都是数组)用于保存状态数据,一开始没有意识到这一点,导致对全局变量的访问散落在好几个脚本文件里,RDT下看起来红通通的一片 极其不爽。那么就重构吧——封装数组重构,将对这些全局数组的访问和修改操作统一到一个模块,调用全局变量的地方都引用这个模块,通过模块去操作全局变 量,代码看起来清爽多了。
发表评论
我的留言簿
-
你好,看过你关于自定义classloader的回帖,想问问几个问题:
  ...
-- by llp20_2000
最近加入圈子
最新评论
-
Ruby Tip——读文件
花花公子 写道IO.read("test.log")嗯,这个方法我是知道的,我前 ...
-- by dennis_zane -
Ruby Tip——读文件
IO.read("test.log")
-- by 花花公子 -
一封邮件
咋我没收到呢....
-- by yangzhihuan -
漂亮的代码
说得比较深.看的时候,觉得句句都正中心坎.看完之后,好像没啥收获.还是要自己试过 ...
-- by yangzhihuan -
广州opensource camp小记
貌似你那件open source camp的T-shirt背后很多广告滴说.
-- by yangzhihuan







评论排行榜