锁定老帖子 主题:探索设计模式之六——单例模式
精华帖 (2) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (7)
|
|
---|---|
作者 | 正文 |
发表时间:2010-01-22
每个月都会有人用差不多的帖子来讲解一下Singleton...
|
|
返回顶楼 | |
发表时间:2010-01-22
IcyFenix 写道 robertliudeqiang 写道 呵呵,楼主总结的比较全,如果能加上单例模式在不同classloader上的分析,甚至是多个jvm的分析就好了。
另外,最近一期“程序员”杂志刊登了一篇采访 GoF(设计模式作者)的文章,他们计划对<设计模式>进行修订,其中还特别提到要剔除“单例模式”,认为单例模式很容易在系统中产生“代码的臭味”,期待新版的设计模式早点出来。 你好,你和另外一位网友都提到不同类加载器对singleton模式的影响,刚刚看到你blog中的一篇文章:http://robblog.iteye.com/blog/576351,我接着你文章的例子补充一下。 多个classloader可以加载同一个类,加载器1加载了ClassA,创建出来的ObjectA去instanceOf加载器2加载的同一个ClassA,结果是false的,用==或者equals比较2个加载器中实例化出来的对象自然肯定也是false。这是你blog文中的例子描述的内容。 接着我继续引申文中的例子,在tomcat中存在的多个加载器,从上至下的顺序大致是:boot/ext加载器加载jdk以及jdk的/lib/ext包,common/share加载器加载common/lib、share/lib中的包,webapp加载器加载应用程序的lib、classes目录中的包,这是很多人都了解过的知识,那是否有人察觉到下面这种很常见的场景可能会产生的问题: 场景:很多程序都spring来管理,一般的做法是将spring.jar放到common/lib中,将自己的类放到应用程序的/lib或者/lib/classes中。根据java的默认加载类、创建对象的规则(就是不特别指定类加载器的情况,譬如使用new创建对象,或者使用一个参数的Class.forName()重载来创建对象),当遇到新的类需要加载时,使用的是加载当前类的类加载器去加载(很多classloader的实现又优先委派给自己的父classloader去加载了,除了osgi中,其他大多都是这种场景,这个与当前话题无关先放下),现在就出现一个问题了,spring.jar因为是放在common/lib中的,它的类加载器自然是common加载器,那为何spring还能管理到我们应用程序呢?放在应用程序的/lib目录下的东西应当对spring的类加载器是不可见的才对呀? 提出上面这种场景,是因为这里遇到的问题和单例模式下处理多个类加载器中的主流方式是一样的,都是使用Thread.currentThread().getContextClassLoader()中的加载器去加载类,因为各种应用服务器一般会分配请求处理线程的时候,将这个加载器设置为应用程序加载器(譬如tomcat中的webapp加载器),从而使得上级加载器中加载的代码也能有途径访到我们应用和程序中的代码。 以后有机会再重新整理这篇文章的时候,我把这些补充进去。希望能对你有所帮助。 挺好,先收藏。 |
|
返回顶楼 | |
发表时间:2010-01-25
Effective java 2 建议java1.5以上使用单元素的枚举实现Singleton.
|
|
返回顶楼 | |
发表时间:2010-01-29
单例模式因为其相对简单,尤其是从面向过程的角度看,它非常受欢迎,所以我们看到处看到滥用单例的例子。
|
|
返回顶楼 | |
发表时间:2010-01-30
最后修改:2010-01-30
你第六次尝试的范例我在某个项目中使用过,在单例中使用double check 我没有深入了解,虽然偶尔也写double check,至于为什么double check也会有漏洞并不清楚,今天看了一下楼主的帖子受益匪浅。
不过坦率地讲,现在的应用引入依赖注入容器之后单例看起来已经不是问题了。 |
|
返回顶楼 | |
发表时间:2010-04-02
学习了. 分析的很透彻. 一会写个测试程序实践下.
|
|
返回顶楼 | |
发表时间:2010-10-28
受益匪浅。
|
|
返回顶楼 | |
发表时间:2010-11-08
饿汉式的创建方式在一些场景中将无法使用:譬如Kerrigan实例的创建是依赖参数或者配置文件的,在getInstance()之前必须调用某个方法设置参数给它,那样这种单例写法就无法使用了。
/** * 实现单例访问Kerrigan的第五次尝试 */ public class SingletonKerriganE { /** * 单例对象实例 */ private static SingletonKerriganE instance = new SingletonKerriganE(); private SingletonKerriganE(){ //init config 可以在这里进行配置文件的初始化吗? } public static SingletonKerriganE getInstance() { return instance; } }
这样看看行否各位XDJM? |
|
返回顶楼 | |
发表时间:2010-12-10
,只需要将instance的定义改成“private volatile static SingletonKerriganD instance = null;”就可以保证每次都去instance都从主内存读取,就可以使用DCL的写法来完成单例模式。,,,如何解决上面提到的1—3—2问题,可否详细说明
|
|
返回顶楼 | |
发表时间:2010-12-10
上次看外国一个编程论坛上说java不支持双重检测。
|
|
返回顶楼 | |