动机
有时候只有一个类的实例是很重要的。比如,一个系统应该只有一个窗口管理实例。
单例模式是最简单设计模式:类负责实例化自己,确保只有一个实例,并且提供一个访问这个实例的入口。
目的
1. 确保只有一个实例被创建。
2. 提供访问这个实例的入口。
实现
使用final确保被创建一次,private的构造函数确保不被实例化。public的getInstance方法确保外部能够访问。下面是饿汉模式:
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
懒汉模式:
public class SingletonDemo {
private static volatile SingletonDemo instance = null;
private SingletonDemo() { }
public static SingletonDemo getInstance() {
if (instance == null) {
synchronized (SingletonDemo .class){
if (instance == null) {
instance = new SingletonDemo ();
}
}
}
return instance;
}
}
适用场景和实例
1. Logger类,防止每次打印log的使用都创建一个Logger实例。
2. 控制类,一般整个系统都只有一个控制实例。
具体问题和实现
1. 线程安全,健壮的单例模式应该是线程安全的。
2. 懒汉模式使用了双重锁机制。
3. 饿汉模式使用静态变量,在程序加载时就实例化,保证了只有一个实例。
4. 抽象工厂和工厂方法通常被设计成单例模式,以保证只有一个工厂。
5. 使用序列化和反序列化时,会有多个实例被创建,使用readResolve函数避免这个情况,不过最好是不要使用序列化。
public class Singleton implements Serializable {
...
// This method is called immediately after an object of this class is deserialized.
// This method returns the singleton instance.
protected Object readResolve() {
return getInstance();
}
}
关键点
1. 在多线程的程序中,要注意数据的同步。
2. 序列化时要使用readResolve方法返回实例,避免多个对象被创建。
3. 如果被多个类加载器加载时,会有多个实例被创建。
上文参考了: