关于用私有构造器或者枚举类型强化Singleton属性
Singleton是仅仅被实例化一次的类,一般在我们实现的时候是有三种实现方式,第一种就是使用公有域的方式去实现。例如:
public Class Elvis{
public static final INSTANCE =new ELVIS();
//将构造函数设为私有的
private Elvis(){}
public void otherMethods(){}
}
将构造函数设为私有不可进行外部创建,保证该类只能被实例化一次,并且通过final的修饰符进行修饰可以保证该类不能被修改。
实现singleton的第二种方式就是通过静态工厂的方法去实现。例如:
public Class Elvis{
private static final Elvis INSTANCE =new Elvis();
private Elvis(){}//私有化构造器
//设置公有的静态方法
public static Elvis getInstance(){return INSTANCE;}
}
以上两种方法各有优缺点:
使用公有域的方法可以优势是比较简单线程安全,但是不会防止反射机制的攻击,反射攻击会导致有两个对象
静态工厂方法的优势在于提供了灵活性可以通过方法的引用发作为提供者。但是线程是不安全的,需要借助双重锁去实现singleton。
以上两种方法在实现序列化的时候都要提供一个readResolve方法去声明每个实例域都是瞬时的,要不然会导致序列化和反序列化以后的对象不一致。
而第三种方法就是通过枚举类型来创建singleton,声明一个包含单个元素的枚举类型。例如:
public enum Elvis{
INSTANCE;
public void otherMethods(){}
}
仅仅通过简单的几行代码就实现了singleton 并且无偿提供序列化机制,并且能够应对反射攻击,但是当singleton必须实现一个超类的时候这个方法是不合适的。
以上来自Effiective Java 中的读书笔记。