Java 经验法则3 用私有构造方法或枚举类型强化Sigleton属性

2013-11-21

Java 经验法则3 用私有构造方法或枚举类型强化Sigleton属性

2013-11-21

单例

Singleton指仅仅被实例化一次的类。也就传说中得单例。

一般实现Singleton方法如下:

饿汉模式1

public class Elvis{
    public static final Elvis INSTANCE = new Elvis();
    private Elvis(){
        //...
    }
    public void sayHello(){...}
 
}

饿汉模式2(使用静态工厂方法访问,推荐)

public class Elvis{
    private static final Elvis INSTANCE = new Elvis();
    private Elvis(){
        //...
    }
 
    public void sayHello(){...}
 
    public static Elvis getInstance(){
        return INSTANCE;
    }
}

饿汉模式3

public class Elvis{
    private Elvis INSTANCE = null;
    static{
        INSTANCE = new Elvis();
    }
    private Elvis(){
        //...
    }
 
    public void sayHello(){...}
 
    public static Elvis getInstance(){
        return INSTANCE;
    }
}

懒汉模式1(延迟加载,线程不安全)

public class Elvis{
    private static Elvis INSTANCE = null;
    private Elvis(){
        //...
    }
 
    public void sayHello(){...}
 
    public static Elvis getInstance(){
        if(INSTANCE == null){
            INSTANCE = new Elvis();
        }
        return INSTANCE;
    }
}

懒汉模式2(延迟加载,线程安全,效率略低)

public class Elvis{
    private static Elvis INSTANCE = null;
    private Elvis(){
        //...
    }
 
    public void sayHello(){...}
 
    public static synchronized Elvis getInstance(){
        if(INSTANCE == null){
            INSTANCE = new Elvis();
        }
        return INSTANCE;
    }
}

静态内部类(延迟加载,线程安全,推荐)

public class Elvis{
    private static class SingletonHolder{
        private static final Elvis INSTANCE = new Elvis();
    }
    private Elvis(){
        //...
    }
 
    public void sayHello(){...}
 
    public static final Elvis getInstance(){
        return SingletonHolder.INSTANCE;
    }
}

单元素枚举类型(线程安全,无偿序列化,防止反射攻击,极力推荐)

public enum Elvis{
    INSTANCE;
 
    private Elvis(){...}
 
    public void sayHello(){...}
}

注:除了枚举方式实现,以上方法实现Singleton的类序列化需要以下操作

  1. implements Serializable
  2. 加入以下方法
private Object readResolve(){
    return INSTANCE;
}

枚举Singleton优势

  1. 自由序列化;
  2. 保证只有一个实例(即使使用反射机制也无法多次实例化一个枚举量);
  3. 线程安全

枚举Singleton缺点

  1. 失去了一些类特性
  2. 不能延迟加载