定义:
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
讲解:
让类自身负责保存它的唯一实例,这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问(获取)该实例的方法。
单例类应满足以下特点:
- 单例类只能有一个实例。
- 单例类必须自己创建自己的唯一实例。
- 单例类必须给所有其他对象提供这一实例。
类图:
角色:
单例类(Singleton):自己实例化自己的唯一实例,并提供访问该唯一实例的方法。
饿汉式单例:
public class Singleton {
//私有的静态变量
private static final Singleton singleton = new Singleton();
//私有的构造方法
private Singleton() {
}
//静态方法
public static Singleton getInstance() {
return singleton;
}
}
从本例中可以看到因为Singleton类的构造方法是私有的,因此外部类无法用new来实例化Singleton类,而只能通过Singleton类本身实例化自己。私有静态变量singleton在Singleton类被加载的时候进行实例化,然后通过getInstance静态方法获取实例化后的Singleton类实例。这样就可以通过getInstance方法获取Singleton类的唯一实例。因为在Singleton类加载时进行实例化,所以此种写法也称为饿汉式单例类。
优点:
- 在类加载的同时已经创建好了一个私有的静态单例对象singleton,调用getInstance方法时反应速度快。
缺点:
- 资源效率不高,可能getInstance方法永远不会被调用,但调用该类的其他静态方法或者加载了该类(class.forName),那么这个实例仍然会初始化。
- 由于构造方法为私有的(private),因此无法被继承。
懒汉式单例:
public class Singleton {从本例中可以看到与饿汉式单例类不同的是,Singleton类在加载时不在实例化自己,而是在getInstance静态方法中进行实例化。同时为了避免在多线程的情况下调用getInstance方法时会出现多个实例的情况,增加了synchronized关键字以保证线程的安全性。此种写法也称为 懒汉式单例类。
//私有的静态变量
private static Singleton singleton = null;
//私有的构造方法
private Singleton() {
}
//静态方法
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
优点:
- 资源利用率高,不调用getInstance方法,单例singleton对象就不会被实例,可以调用该类的其他静态方法。
缺点:
- 第一次调用getInstance方法时,如果初始化比较耗时,等待时间会过长。
- 使用synchronized关键字同步,则会增加不必要的系统开销。
- 由于构造方法为私有的(private),因此无法被继承。
使用场景:
- 在一个系统中,要求一个类只有一个实例时,应该考虑使用单例模式。
- 在一个系统中,如果需要频繁的创建和销毁一个实例的话,应该考虑使用单例模式。
- 如果一个对象的实例化过程比较耗时,并占用大量资源,而又频繁使用时,应该考虑使用单例模式。
注意:饿汉式单例和懒汉式单例由于构造方法为私有的(private),所以无法实现继承关系。为了实现继承的单例类,可以参考登记式单例类,本文不做过多介绍。