23种设计模式之【单例模式】

时间:2022-09-09 08:33:03

定义:

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

讲解:

让类自身负责保存它的唯一实例,这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问(获取)该实例的方法。

单例类应满足以下特点:

  • 单例类只能有一个实例。
  • 单例类必须自己创建自己的唯一实例。
  • 单例类必须给所有其他对象提供这一实例。

类图:

23种设计模式之【单例模式】

角色:

单例类(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 {
//私有的静态变量
private static Singleton singleton = null;
//私有的构造方法
private Singleton() {
}
//静态方法
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
        从本例中可以看到与饿汉式单例类不同的是,Singleton类在加载时不在实例化自己,而是在getInstance静态方法中进行实例化。同时为了避免在多线程的情况下调用getInstance方法时会出现多个实例的情况,增加了synchronized关键字以保证线程的安全性。此种写法也称为 懒汉式单例类。

优点:

  • 资源利用率高,不调用getInstance方法,单例singleton对象就不会被实例,可以调用该类的其他静态方法。

缺点:

  • 第一次调用getInstance方法时,如果初始化比较耗时,等待时间会过长。
  • 使用synchronized关键字同步,则会增加不必要的系统开销。
  • 由于构造方法为私有的(private),因此无法被继承。

使用场景:

  • 在一个系统中,要求一个类只有一个实例时,应该考虑使用单例模式。
  • 在一个系统中,如果需要频繁的创建和销毁一个实例的话,应该考虑使用单例模式。
  • 如果一个对象的实例化过程比较耗时,并占用大量资源,而又频繁使用时,应该考虑使用单例模式。

注意:饿汉式单例和懒汉式单例由于构造方法为私有的(private),所以无法实现继承关系。为了实现继承的单例类,可以参考登记式单例类,本文不做过多介绍。