模式回顾---单例

最近突然想回顾一下设计模式,很多东西是要回过头来总结一下的。今天先回顾一下单例吧。
很多时候觉得挺搞笑的,去面试的时候如果人家问你设计模式,一般都是要你写个单例模式。去年来北京好几家面试都是问我这个。当时我就想这个能反映出一个人的水平来吗?还是说更多的是反映出这个公司的水平呢?
随着一年的应用,很多地方都用过之后觉得,单例这个东西虽然简单,可是现实是复杂的。所以单例这个简单的模式也不能太小瞧咯。
单例其实有很多种实现,这是其中的一种,延迟加载的(好像英文叫Lazy?):
[下面代码中所有的构造器都是私有的,这里我就省略不写了。]
public class ClassName {
    
public static ClassName getInstance(){
        
if(instance == null)
        {
            instance 
= new ClassName();
        }
        
return instance;
    }
    
    
private static ClassName instance;
}
这种的好处是我们的单例使用时才进行初始化,这样方便我们在系统启动时做些小动作。但是这个方式不是线程安全的,想要完成一个线程安全的单例,有几种方式:
(一)
public class ClassName {
    
public static ClassName getInstance(){
        
return instance;
    }
    
    
private static ClassName instance = new ClassName();
}
这种方式,可以保证我们的单例是线程安全的,毕竟我们唯一的实例在系统初始化的时候就构造了。可是Java的机制是static级别的变量初始化时互相调用是会报异常的。所以随着系统的扩展,尤其还会有一些新手或者粗心大意的家伙(比如说,我)会乱用你的方法。一不小心就造成问题了。而且,你也失去了第一个方式中的一个小优势,不能在系统启动时做点小动作了。
(二)
public class ClassName {
    
public static synchronized ClassName getInstance(){
        
if(instance == null)
        {
             instance 
= new ClassName();
        }
        
return instance;
    }
    
    
private static ClassName instance;
}
这样倒是线程安全了,也可以延迟加载,但是从今以后这个getInstance方法就是synchronized的了,那绝对是很影响效率的。我跟朋友讨论提出了几种写法,以期既能使单例可以在系统启动不至于数据已经煮成熟饭又是线程安全的:(少数人讨论结果,代码可能会比较丑陋,仅供参考,欢迎拍砖)

public class ClassName {
    
public static ClassName getInstance(){
        
if(instance == null)
        {
             instance 
= ClassName.createInstance();
        }
        
return instance;
    }
    
    
private static synchronized ClassName createInstance(){
        
if(instance == null)
        {    
            
return new ClassName();
        }
else{
            
return instance;
        }
    }
    
    
private static ClassName instance;
}
这种写法就很好的解决了这些问题。
还有一种写法是这样的,这个不是延迟加载的。而是采用了一种取巧的方式。
public class ClassName {
    
public static ClassName getInstance(){
        
if(!instance.isInit)
        {
             instance.initSingleton();
        }
        
return instance;
    }
    
    
private synchronized void initSingleton() {
      
if(!isInit)
      {
          reset();
//这名字是有点怪异,我没时间想太好听的名字
          isInit = true;
      }
    }
    
    
public void  reset(){
        
//.....真正进行数据初始化的地方
    }
    
    
private boolean isInit = false;
    
    
private static ClassName instance = new ClassName();
}

将所有的初始化代码搬到构造器之外。这是专为数据初始化和复位进行的设计。所以我把reset开放了出来。



posted on 2008-01-29 21:59 咖啡屋的鼠标 阅读(1437) 评论(7)  编辑  收藏 所属分类: Java

评论

# re: 模式回顾---单例 2008-01-30 09:30 久城

我一般用的都是这种:
public class ClassName {
public static ClassName getInstance(){
if(instance == null)
{
instance = new ClassName();
}
return instance;
}

private static ClassName instance;
}  回复  更多评论   

# re: 模式回顾---单例 2008-01-30 10:05 大卫

不错!  回复  更多评论   

# re: 模式回顾---单例 2008-01-30 10:51 dennis

public class ClassName {
public static ClassName getInstance(){
if(instance == null)
{
instance = ClassName.createInstance();
}
return instance;
}

private static synchronized ClassName createInstance(){
return new ClassName();
}

private static ClassName instance;
}
这种写法有问题的,可以想象下,线程A判断instance==null,然后开始createInstance,正在此时,线程B也判断instance==null,然后等待线程A完成创建并解锁,然后线程B也createInstance,这还是单例吗?单例模式的写法网上已经讨论烂了,这样的错误实在不应该。  回复  更多评论   

# re: 模式回顾---单例 2008-01-30 10:52 dennis

第三种写法就更无语了,静态初始化,更谈不上所谓的lazy initialize了。基础还是好好看下吧。  回复  更多评论   

# re: 模式回顾---单例 2008-01-30 10:54 dennis

ps:我所说的第三种是最后那个。
既然发表在blogjava首页上,文章至少要保证没有错误,不然误导人也是害人害己,说的严重了,博主自己看看。  回复  更多评论   

# re: 模式回顾---单例 2008-01-30 11:45 咖啡屋的鼠标

@dennis
感谢您的批评指正,这个写法是有点问题。昨天跟朋友讨论出这个方法的时候没考虑细,刚才看了看,改改也能使用,可能就丑陋点了。先删去。

至于最后一种,确实不是lazy的,我看了看也没写是Lazy的,应该不会有误导概念的问题,但还是标明了一下以防止误会,很感谢你的指出。我只是把所有的初始化代码放到了init里面,在构造器里不做任何操作初始化操作,其实还应该做一次是否初始化的二次判断。省的多次初始化,但是那样我就还要再写一个函数来控制复位,说起来可能会更繁琐,就没加。

  回复  更多评论   

# re: 模式回顾---单例 2008-01-30 13:18 咖啡屋的鼠标

考虑了一下,还是趁中午的时间把改正的结果更新了,经过简单的多线程测试是没有问题的。  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 
<2008年1月>
303112345
6789101112
13141516171819
20212223242526
272829303112
3456789

导航

统计

常用链接

留言簿(15)

随笔分类(52)

随笔档案(76)

文章分类(3)

文章档案(4)

新闻档案(1)

收藏夹

Flex

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜