JR 精品文章 - 再论Singleton模式
AD: jr (at) javaresearch.org


首页 | 动态 | 文章 | FAQ  | 新闻 | 下载 | 代码 | 工作 | 调查 | 术语 | 站点 | 图书 | 论坛 | 帮助 | 全部  

TOP | 交流 | 软件 | 专栏 | 开源 | 译/著 | 源码 | API  | 推荐 | FTP  | 积分 | 统计 | 搜索 | Blog | 我们  
首页 » 研究文集 » 设计及设计模式 搜索标题相关文章 搜索标题相关文章    评论此文章 发表评论     开始监控此文章 开始监控   加入收藏夹  加入收藏夹
再论Singleton模式
sheldonsun 原创   更新:2006-10-30 14:06:59  版本: 1.0   

Singleton模式可能是应用最广泛的模式之一了, 但有些错误的应用。

Singleton的实现: 有两种方式, 如下:
1. class Test {
    public static final Test instance = new Test();
    private Test() {}
}

2. class Test {
   private static final Test instance = new Test();
   private Test() {}
   public static Test getInstance() {
       return instance;
   }
}

这两种方法都要求构造器是私有的, 这样就可以防止该类外的对象创建新的TEST对象。

但相对而言, 推荐使用第二种方法, 因为其更具有灵活性,当我们改变创建对象的方式的时候, 不需要改动客户代码。 第一种方法较第二种有一点完全可以忽略不计的效率的提高。

但应避免如下代码实现Singleton:

class Test {
    private static Test singleton = null;
    private Test() {}
    public Test getSingleton() {
    if(singleton == null) {
            singleton = new Test();
    }
    return singleton;
}
}

因为严格上讲, 这并不能完全实现Singleton模式,而且会导致程序出错,  这同著名的线程问题--DCL实效的原理是完全一样的:JVM创建对象的过程可以分为几个步骤:创建空间, 把所有的变量赋值位默认值, 初始化。。。 当有两个线程A和B同事进入该方法, A先执行, A创建Test实例的空间, 这时,因为CPU的指令流机制,时间片段正好轮到B线程, 这时B判断singleton是否为NULL, 因为A已经为Test的实例分配了空间, 所以JVM认为实例已经创建了, B继续执行, 更糟糕的是B调用了singleton, 这时因为他并没有初始化完全, 所以抛出NullPointerException, 太糟糕了!

版权声明   给作者写信
本篇文章对您是否有帮助?  投票:         投票结果:     24       2
作者其它文章: 作者全部文章
评论人:82529gfl 发表时间: Wed Nov 01 11:33:10 CST 2006
不同意作者的观点!
class Test {
    private static Test singleton = null;
    private Test() {}
    public Test getSingleton() {
    if(singleton == null) {
            singleton = new Test();
    }
    return singleton;
}
}
这种应该称为Singleton中的惰性初始化,虽然对Multi-Thread Program有可能出错,可能出现多个实例,我们可以这样解决,加上同步:
class Test {
    private static Test singleton = null;
    private Test() {}
    public Test synchronized getSingleton() {
    if(singleton == null) {
            singleton = new Test();
    }
    return singleton;
}
}
评论人:MiMiEye 发表时间: Wed Nov 01 19:25:39 CST 2006
是的,同意我楼上兄弟的观点
而且视应用场合来判断那种方式更合理些.(主要是一种是只要类加载器一加载类时,自己的实例是否被创建的区别)
评论人:82529gfl 发表时间: Thu Nov 02 13:28:43 CST 2006
[:D]
JVM的内存是有限的,并且我们的程序也要给用户友好的感觉。
其实初始化也是一个很矛盾的话题,我们当然希望能在程序启动时尽可能多的初始化或者取得我们需要的数据,但是这样做的后果就是可能OutofMemory或者是我们的启动速度异常的慢。我们只能做到必要的去初始化一些数据,其他的数据以后用到的时候再去取得或者去初始化,这就使用到了惰性初始化。
评论人:hyhongyong 发表时间: Fri Nov 03 10:11:34 CST 2006
文章好,评论更好!![good][good]
评论人:oboaix 发表时间: Fri Nov 03 12:32:21 CST 2006
学习中,[cop]
评论人:lsg_zju 发表时间: Sun Nov 05 13:23:44 CST 2006
作者说的最后一个不好的方法,引用如下:
class Test {
    private static Test singleton = null;
    private Test() {}
    public Test getSingleton() {
      if(singleton == null) {
            singleton = new Test();
      }
      return singleton;
  }
}
那么如何获得Test类的实例呢?

构造方法是私有的,getSingleton()方法不是静态的
应该在作者的第二种实现的getSingleton前加上synchronized吧? 

“再论Singleton模式”第一论我并没有看过
一点拙见,请指教

评论人:lsg_zju 发表时间: Sun Nov 05 13:28:31 CST 2006
应该把最后一个方法加上静态的和synchronized
前面说错了
刚发上去看不到
所以先留下这句话
观望ing
评论人:jinyi1161 发表时间: Mon Nov 06 09:58:02 CST 2006
[:)]
评论人:zhyiwww 发表时间: Mon Nov 06 10:40:37 CST 2006
把上面的那段程序改成下面的代码:
class Test {
    private static Test singleton = null;
    private Test() {
          if(singleton == null) {
            singleton = new Test();
          }
    }
    public Test getSingleton() {

    return singleton;
}
}
不知道这样实现可以吗?
评论人:wangminbyxy 发表时间: Tue Nov 21 21:32:22 CST 2006
同意二楼初始化,惰性初始化在某种意义上是比较好的,加上同步,就可以了
评论人:pdw2009 发表时间: Thu Nov 30 23:44:56 CST 2006
应该看看《JAVA与模式》这本书,这有详细的说明
评论人:mrou2001 发表时间: Thu Dec 07 14:31:02 CST 2006
加油啊,支持[java]
评论人:wangdi 发表时间: Mon Jan 08 11:47:08 CST 2007
http://www.jdon.com/designpatterns/singleton.htm
评论人:wangdi 发表时间: Mon Jan 08 12:07:39 CST 2007
  1. public class SingletonDemo {
  2. //第一种方式
  3.     private static SingletonDemo instance = new SingletonDemo();
  4.     private SingletonDemo(){}
  5.     public static SingletonDemo getInstance(){
  6.         return instance;
  7.     }
  8. //第二种方式
  9. //    private static SingletonDemo instance = null;
  10. //    public static synchronized SingletonDemo getInstance() {
  11. //        if(instance == null){
  12. //            instance = new SingletonDemo();            
  13. //        }
  14. //        return instance;
  15. //    }
  16. }
评论人:maojinyw 发表时间: Tue Jun 03 14:35:28 CST 2008
学习了...[good]

这个文章共有 15 条评论
主题: Factory模式的作用 上一篇文章
返回文章列表 返回〔设计及设计模式〕
下一篇文章 主题: JAVA的设计模式 (1)


文字广告链接
        自主、快速定制基于JAVA的B/S业务系统          重量级企业在线自定义WEB报表平台
        Excel制表、零代码发布、打印、图表结合——快逸报表,免费、稳定、功能强大的java工具
        技术圈: 关于Java、dotNet、PHP、Ruby、奇客、Web2.0等更多资讯博客精选文章

关于 JR  |  版权声明  |  联系我们 

©2002-2006 JR 版权所有 沪ICP备05019622号