论坛首页 Java企业应用论坛

Singleton和Static的缺点(重发)

浏览 18728 次
该帖已经被评为精华帖
作者 正文
   发表时间:2004-04-17  
dlee 写道
说来说去离题越来越远了。今天在上班,晚些时候把 GOF 原创的《设计模式》中关于 Singleton 的段落找来大家讨论一下。
大家讨论问题都需要这样汪洋恣肆吗?是不是惟有这样才能显示出自己掌握了“人间正道”呢?

题目其实很清楚,我的观点也是很清楚:寻找方法,首先要切割问题.
0 请登录后投票
   发表时间:2004-04-17  
我还是要给trustno1兄一个建议,就是不要为了反对别人而进行讨论,这样容易跑题。

就femto所言,singleton和static没有了多态性,但这并非不是OO。在现实中的确是需要单态的抽象,这完全是根据情况而言的。虽然,只是说根据情况而言有点不把‘革命进行到底的感觉’,但In short,这样说没什么不对。具体的说,谈到一个中国的问题时,就需要一个中国这个对象,此时需要单例。在说中国人时就不能是单例。这个道理很简单,说根据情况而言应该是合理省略,何必批评别人看问题的方法论呢?
0 请登录后投票
   发表时间:2004-04-17  
又仔细地看了一下 GOF《设计模式》中关于 Singleton 的描述,发现  femto 所说的问题完全不是 Singleton 带来的,也就是说 femto 在这里散布了一个小小的 FUD。
femto 所说的问题是他没有正确理解 Singleton 造成的。Singleton 只是保证你只会得到某一类对象的一个实例,它并不会阻碍你改变对象方法的实现。也就是说它只跟那个静态的类方法 Instance() 有关,与其它的对象方法没有关系,其它的对象方法没有写好不要怪罪到 Singleton 头上。正确的解决方法是定义一个简单的 Singleton 基类,然后分别定义两个子类 DBLockManager 和 MemLockManager。通过环境变量或者属性文件指定要使用哪个 Singleton 的子类。这两个子类分别实现自己的 lock() 和 unlock() 方法(应该把 lock() 和 unlock() 放在一个接口中,然后 DBLockManager 和 MemLockManager 两个类都实现这个接口,这个接口与 Singleton 基类是没有任何关系的),彼此没有任何影响。这是一个很简单的重构过程,用 Eclipse 在 10 分钟之内就可以完成。
femto 遇到的问题是因为他们最初开发时未能充分考虑设计的灵活性导致的,可以说与 Singleton 本身没有任何关系。

详情请看《设计模式》中 Singleton 的代码示例,尤其请搞清楚如何为 Singleton 生成子类以及如何在父类的静态 Instance() 方法中注册子类对象的内容(就是那个 Lookup() 方法)。

至于这句:
引用
不过从这个例子确实体会到Singelton不是什么好东东:),一用就耦合与具体的类了,
那就更是无稽之谈了。
0 请登录后投票
   发表时间:2004-04-17  
Singleton在实际使用中确实和工厂模式一起用的,
它主要用来只生成对象的一个实例,比如配置文件,Jdon上讲jive源代码时有过案例
0 请登录后投票
   发表时间:2004-04-17  
建议大家都去认真读一下《设计模式》这本书,而不要把什么 Jive 当作学习设计模式的必然选择,这样会产生很多误解的。Jive 也不是什么实用的好东西。
我读书喜欢从源头读起。儒家经典我读的很少,我只读过《论语》、《荀子》,其他人如朱熹一类的书皆不足观。道家经典我也只读过《老子》、《庄子》,但是我觉得已经足够了。变化都在这几本书里,后人的著作无非就是以不同的方式来解释圣人之言罢了。所谓的“半部论语治天下!” 话扯远了,呵呵。
0 请登录后投票
   发表时间:2004-04-17  
有时候我觉得Trustno1的观点并没有问题,但是表达的方式往往会给人“你们都不行”的印象。而被回帖的人,往往就被某种情绪蒙蔽,偏离了主题。

这也就是我们常常发现的,Trustno1参加的帖子,往往会跑题的原因,他自己倒是一般都不跑题的:)

Singletond的问题,他说的也没什么不对,但是不如dlee那么客气罢了。
0 请登录后投票
   发表时间:2004-04-17  
呵呵,我想起了象棋大师的心理战术,据说胡荣华大师就是此中高手,不知道有多少英雄都落入了他的毂中。
0 请登录后投票
   发表时间:2004-04-17  
dlee 写道
呵呵,我想起了象棋大师的心理战术,据说胡荣华大师就是此中高手,不知道有多少英雄都落入了他的毂中。


都说搞软件的人最理性,其实啊,获得这样的修养不容易。
0 请登录后投票
   发表时间:2004-04-17  
我再补充约束一下singleton模式的功能吧。基本上它有两方面的应用,其一是楼上dlee写的,也就是生成唯一实例,它主要的目的是避免产生过多而不需要的实例。另外一个功能,大家也许用的少,我以我个人的经验说一说吧。大家在做多线程编程的时候,如果要保证两个线程间负责通信,那么就需要一种通信方式,因为线程是并行运行的,所以它不适合用observer模式,那么就需要一个通信介质。我们知道,对于基本数据类型,传递是值拷贝,所以不能用来做通信介质,所以我们需要用到对象来作为通信介质。有人会问这和singleton模式有联系么?的确,我们可以通过对两个线程传递同一个变量就可以了。但是这样,就将两个线程间显示的耦合化了,那么如果要增加第三个线程,就必须更改启动线程的方法,加入通信对象的传递。这个时候如果我们用singleton模式,每个线程在内部得到singleton的对象实例(所有线程得到的都是同一个,从而代替通信介质传递的问题),那么就可以将线程间的关系的耦合化降低。
    另外,就楼上Trustno1兄的提的问题讲一下,我说的Template模式和你说的是不同的,你说的是一种泛型,这个是c++中非常好的功能,在JDK1.5也支持,我也很赞成,它可以部分代替多态。我说的template模式大致的解释是定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。举例说,一条生产线有先后组装汽车的步骤,而我们只需要定义好这个流程(也就是在抽象类实现),然后所有的子类只需要实现具体零件的生产(也就是build方法),然后对于客户端,它只关心汽车的生产(defineFacade),就是这么简单。你可以用接口实现(其实也就是用Proxy模式)试一试,这个时候,你可以比较比较它带来的复杂性。
    好了,上述两个都是就具体问题的说明,希望大家满意哦~~~~~~~~~
      我决定,多做实事,少说废话了,呵呵~~~~~~~~~
0 请登录后投票
   发表时间:2004-04-17  
继续说明关于singleton模式的错误使用情况。
   一般来说,对于会产生多并发或者说资源性的对象,是不太赞成使用singleton模式的,它会带来两个问题,第一,为了保证资源安全,那么你需要同步,第二,也就是因为同步它会带来性能上的较大问题。
   我不知道大家是否看过struts的源代码,在struts中的action就是采用singleton模式,所有的action都是唯一实例,调用的时候通过同步来限制,我和mikeho也讨论过,都不是太理解,甚至反对。dlee第一个引用的帖子说spring的实例产生有两种,一种是singleton,一种是prototype,我觉得很不错(虽然没有研究过spring的源代码),这是一个我个人认为很好的方法。
    上述的讨论只是反映了singleton模式被滥用了会带来的问题和后果,但是丝毫无法反对正确使用singleton可以带来的好处。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics