Effective Java笔记第一章创建和销毁对象
第三节用私有构造器或者枚举类型强化Singleton属性
1.Singleton指仅仅被实例化一次的类。使类成为Singleton会使他的客户端测试变得十分困难。Java1.5之前,实现Singleton有两种方法,这两种方法都要把构造器保持为私有的,并导出公有的静态成员变量,以便允许客户端能访问该类的唯一实例。
2.公有静态成员是个final域
public class Demo1 {
//公有静态成员final域
public static final Demo1 INSTANCE = new Demo1();
//私有构造防止实例化
private Demo1() {
}
public void leaveTheBuilding(){
}
public static void main(String[] args) {
Demo1 demo1 = Demo1.INSTANCE;
System.out.println(demo1);
Demo1 demo2 = Demo1.INSTANCE;
System.out.println(demo2);
}
优点:
1)私有构造器仅被调用一次,由于缺少公有的或者受保护的构造器,所以保证了类的全局唯一性。
2)公有域方法的主要好处在于,组成类的成员的声明很清楚地表明了这个类是个Singleton,公有的静态域是final的,所以该域将总是包含相同的对象引用。
缺点:
享有特权的客户端可以借助AccessibleObject.setAccessible方法,通过反射机制调用私有构造器。如果要抵御这种攻击,可以修改构造器,让他在被要求创建第二个实例的时候抛出异常。
3.公有的成员是个静态工厂方法
public class Demo2 {
//公有静态成员final域
private static final Demo2 INSTANCE=new Demo2();
//私有构造防止实例化
private Demo2(){
}
//静态工厂获取对象
public static Demo2 getInstance(){
return INSTANCE;
}
public void leaveTheBuilding(){
}
public static void main(String[] args) {
Demo2 demo2 = Demo2.getInstance();
System.out.println(demo2);
Demo2 demo21 = Demo2.getInstance();
System.out.println(demo21);
}
}
工厂方法的优势:
1)提供了灵活性,在不改变其API的前提下,我们可以改变该类是否应该为Singleton的想法。
2)优势与泛型有关。
3)public域的方法比较简单。
缺点:
容易被修改,比如改成为每个调用该方法的线程返回一个唯一实例。
4.包含单个元素的枚举类型
public enum Demo3 {
INSTANCE;
public void leaveThebuilding(){}
public static void main(String[] args) {
Demo3 demo3 = Demo3.INSTANCE;
System.out.println(demo3);
Demo3 demo31 = Demo3.INSTANCE;
System.out.println(demo31);
}
}
优势:
1)与共有域方法相近,更加简洁,无偿提供了序列化机制,绝对防止多次实例化,虽然还没推广,但单元素的枚举类型已经成为实现Singleton的最佳方法。