Singleton
入门。
Singleton 被翻译作“单例”,也就是说这个类(class)只有这一个实例(instance)。在 Java 中可以这样实现:
class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
首先这个类不提供public
的构造函数,这样保证不能通过构造函数创建新的实例;其次它有一个private static
的实例,不可以被外面直接访问或重新赋值;最后只提供一个get
方法来获得这个实例,而没有set
。
放弃?
这个方法是否有效呢?
// 注:需要import java.lang.reflect.Constructor;
// 获得Singleton的实例
Singleton instance1 = Singleton.getInstance();
// 通过reflection获得构造函数
Constructor constructor = Singleton.class.getDeclaredConstructors()[0];
// 将构造函数设置为可以访问
constructor.setAccessible(true);
// 创建另一个实例
Singleton instance2 = (Singleton) constructor.newInstance();
// 比较两个实例
System.out.println(instance1.equals(instance2)); // => false
System.out.println(instance1.hashCode()); // => 1239731077
System.out.println(instance2.hashCode()); // => 357863579
可以看到这是两个完全不同的实例,有着不一样的hashCode
。
另一个例子:给 Singleton 加上 Serializable 的接口
class Singleton implements Serializable {
...
}
// serialize the instance to file
Singleton instance1 = Singleton.getInstance();
try (ObjectOutput out = new ObjectOutputStream(new FileOutputStream("file.data"))) {
out.writeObject(instance1);
}
// deserailize from file to object
try (ObjectInput in = new ObjectInputStream(new FileInputStream("file.data"))) {
Singleton instance2 = (Singleton) in.readObject();
System.out.println(instance1.hashCode()); // => 152005629
System.out.println(instance2.hashCode()); // => 1307096070
}
可以看到两个实例又是不同的。
进阶!
(更新中。。。)
https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom
http://haokanga.github.io/java/2017/08/09/java-singleton-pattern.html
https://www.geeksforgeeks.org/prevent-singleton-pattern-reflection-serialization-cloning/