单例模式:保证一个类仅有一个实例。
单例模式的三个要点:一是:只有一个实例;二是:它必须自行创建该实例;三是:必须自行向整个系统提供这个实例。
有些类是只需要一个实例就行,象Windows的任务管理器。怎样保证一个类只实例化一次并且易于访问呢?一个全局变量使得一个对象可以被访问,但不能防止你实例化多次。一个更好的办法是让类自身保证它只能实例化一次。可以通过建该类的构造器设置成私有的,然后增加一个公有的访问该实例的方法。这样外部就不能实例化该类。
单例模式的实现有三种,一种是懒汉式;一种是饿汉式;一种是登记式。
懒汉式:
public class LazySingleton{
private static LazySingleton instance=null;
private LazySingleton() {} //私有构造器
public synchronized LazySingleton getInstance(){
if(instance==null){
instance=new LazySingleton();
}
return instance;
}
}
在该类中的synchronized是处理多线程的。 确保当一个线程位于代码的临界区时,另一个线程不能进入临界区。如果其他线程试图进入锁定的代码,则它一直等待,直到该对象被释放。
饿汉式:
public class EagerSingleton{
private static final EagerSingleton instance=new EagerSingleton();
private EagerSingleton() {} //私有构造器
public EagerSingleton getInstance(){
return instance;
}
}
这个类在加载时就会初始化,静态变量instance就被实例化。饿汉式单例类可以在Java内实现,但不易在C++内实现,因为静态初始化在C++中没有固定的顺序。因而变量的初始化与类的加载顺序没有保证,可能会出现问题。
登记式:
这个类实际上是维护一组单例类的实例,这些实例存放在一个Map中,对于已经登记了的,则直接返回,对于没有登记的则先登记后返回。
public class RegSingleton{
private static Map registry=new HashMap();
static {
RegSingleton rs=new RegSingleton();
registry.put(rs.getClass().getName(),rs);
}
protected RegSingleton(){}
public static RegSingleton getInstance(String name){
if(name==null){
name="RegSingleton";
}
if(registry.get(name)==null){
try{
registry.put(name,Class.forName(name).getInstance());
}catch(Exception ex){}
}
return (RegSingleton)(registry.get(name));
}
}
单例模式可以推广到多例。连接池就是多例。