随笔 - 35  文章 - 21  trackbacks - 0
<2010年4月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

常用链接

留言簿

随笔分类

随笔档案

文章分类

搜索

  •  

最新评论

阅读排行榜

评论排行榜


一 基本概念
单例模式是一种为类 提供唯一实例的设计模式。单例模式的目的是为了控制对象的创建,它可以限制创建的数目为一,但在情况改变的时候,也允许灵活地创建更多的对象。因为只有一个实例,所以也只有一套实例的类变量的拷贝,这很像 static 变量。

在 JAVA 中,单例模式不应该被当作一种实现全局变量的方法。更多的,如同工厂模式,单例模式允许你通过 确认某些先决条件是否满足 或者 以 lazily 方式按需创建的方式 来封装和控制创建过程。

二 编程实现
1 饥饿模式 Eager Singleton

public class MySingleton {
    
private static MySingleton fInstance = new MySingleton();
    
    
private MySingleton(){
        
// Construct object 
    }


    
public static MySingleton getInstance(){
        reutnr fInstance;
    }


}

2 懒汉模式 Lazy Singleton

public class MySingleton {
    
private static MySingleton fInstance;
    
    
private MySingleton(){
        
// construct object
    }

    
    
public static synchronized MySingleton getInstance(){
        
if (fInstance == null){
            fInstance 
= new MySingleton();
        }

        
return fInstance;
    }


}

由于只有一个私有构造器,所以单例类是无法被集成的。基于这一点,单例模式并不是一个面向对象模式,仅仅是一个基于对象的模式。

3 饥饿模式基本没有问题,懒汉模式则容易出现一些错误的编程方法
1)
// error, no synchronization on method 
public static MySingleton getInstance() 
 
if (fInstance==null
     fInstance 
= new MySingleton(); 
 }
 

 
return fInstance; 
}

2)
// Also an error, synchronization does not prevent 
// two calls of constructor. 
public static MySingleton getInstance() 
 
if (fInstance==null
   
synchronized (MySingleton.class
      fInstance 
= new MySingleton(); 
   }
 
 }
 
 
return fInstance; 
}
 

3) Double-checked locking 不要使用

public static MySingleton getInstance(){
    
if (fInstance == null ){
        
synchronized (MySingleton.class{
            
if(fInstance == null){
                fInstance 
= new MySingleton();
            }

        }

    }

}

为了避免每次调用 getInstance方法是抓取同步锁的消耗,有人发明了 Double-checked locking 。但不要使用,因为这样的代码将无法在编译器优化和多处理器共享内存的情况下工作。若想详细了解,附录中有对此做详细描述的链接。

三 总结

1 单例模式不应被滥用,比如不能为了得到一个全局变量而创建单例,单例是用于控制对象的创建过程的。只有真正的目的是控制对象创建的过程或数量时,才能考虑使用单例。在大部分情况下,单例模式是有代替方案的。比如经典的数据库连接类被以单例实现,其实可以以对象池模式实现。

2 使用单例模式,尽量使用饥饿模式 ,只有你能预测这个类一定会被创建,那么就可以使用饥饿模式。如果,一定需要推迟对象的创建时间。那么不要使用 Double-checked locking 之类的方法的来提高效率,这将得不偿失。

[1] DoubleCheckedLocking
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
posted on 2010-04-30 21:04 lincode 阅读(205) 评论(0)  编辑  收藏 所属分类: Design pattern

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


网站导航: