02.用私有构造器或者枚举类型强化Singleton属性
Singleton是指仅仅被实例化一次的类。实现Singleton有三种常见的方法:
1.公有静态成员为final域
/**
* 类描述: Singleton with public final field
*/
public class Elvis {
public static final Elvis INSTANC = new Elvis();
private Elvis(){}
}
2.公有成员为静态工厂方法
public class Elvis {
public static final Elvis INSTANC = new Elvis();
private Elvis(){}
public static Elvis getInstanc() {
return INSTANC;
}
}
3.实现序列化接口,控制反序列化创建假冒的实例
public class Elvis implements Serializable {
public static final Elvis INSTANC = new Elvis();
private Elvis(){}
public static Elvis getInstanc() {
return INSTANC;
}
private Object readResolve() {
return INSTANC;
}
}
public static void main(String[] args) {
Elvis firstInstance = Elvis.INSTANC;
String fileName = serializable(firstInstance);
Elvis secondInstance = deSerializable(fileName);
System.out.println(firstInstance == secondInstance);
}
static String serializable(Elvis firstInstance) {
try {
String fileName = "1.txt";
FileOutputStream fos = new FileOutputStream(fileName);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(firstInstance);
oos.close();
return fileName;
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
static Elvis deSerializable(String fileName) {
try (FileInputStream fileIn = new FileInputStream(fileName);
ObjectInputStream in = new ObjectInputStream(fileIn)) {
Object obj = in.readObject();
return (Elvis) obj;
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
4.声明一个包含单个元素的枚举类
public enum Elvis {
INSTANC;
}
public class Test2 {
public static void main(String[] args) throws Exception{
Elvis elvis = Elvis.INSTANC;
Constructor<Elvis> constructor = Elvis.class.getDeclaredConstructor();
constructor.setAccessible(true);
Elvis reflectInstance = constructor.newInstance();
System.out.println(elvis == reflectInstance);
}
}
测试结果:
Exception in thread "main" java.lang.NoSuchMethodException: effective02.Elvis.<init>()
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.getDeclaredConstructor(Class.java:2178)
at effective02.Test2.main(Test2.java:16)
总结
单元素枚举类型经常成为Singleton最佳方法,注意,如果Singleton必须扩展一个超类,而不是扩展Enum的时候,
则不适用适用这个方法(虽然可以声明枚举去实现接口)