Skip to main content

Singleton 单例

Intent

单例模式 (Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

Singleton is a creational design pattern that lets you ensure that a class has only one instance, while providing a global access point to this instance.

Problem

The Singleton pattern solves two problems at the same time, violating the Single Responsibility Principle. 违反了单一职责原则

  1. Ensure that a class has just a single instance. 保证一个类只有一个实例

    The most common reason for this is to control access to some shared resource—for example, a database or a file. 控制某些共享资源 (例如数据库或文件) 的访问权限。

    Here’s how it works: imagine that you created an object, but after a while decided to create a new one. Instead of receiving a fresh object, you’ll get the one you already created.

    Note that this behavior is impossible to implement with a regular constructor since a constructor call must always return a new object by design. 普通构造函数无法实现上述行为, 因为构造函数的设计决定了它必须总是返回一个新对象。

  2. Provide a global access point to that instance. 为该实例提供一个全局访问节点

    Just like a global variable, the Singleton pattern lets you access some object from anywhere in the program. However, it also protects that instance from being overwritten by other code. 单例模式允许在程序的任何地方访问特定对象,但是它可以保护该实例不被其他代码覆盖

Solution

All implementations of the Singleton have these two steps in common:

  • Make the default constructor private, to prevent other objects from using the new operator with the Singleton class. 默认构造函数设为私有
  • Create a static creation method that acts as a constructor. Under the hood, this method calls the private constructor to create an object and saves it in a static field. All following calls to this method return the cached object. 新建一个静态构造方法作为构造函数,该函数会调用私有构造函数来创建对象,并保存在一个静态成员变量中。此后所有对于该函数的调用都将返回这一缓存对象。

If your code has access to the Singleton class, then it’s able to call the Singleton’s static method. So whenever that method is called, the same object is always returned. 无论何时调用该方法,它总是能返回相同的对象

Real-World Analogy

The government is an excellent example of the Singleton pattern. A country can have only one official government. Regardless of the personal identities of the individuals who form governments, the title, “The Government of X”, is a global point of access that identifies the group of people in charge. 政府是单例模式的一个很好的示例。 一个国家只有一个官方政府。 不管组成政府的每个人的身份是什么, ​ “某政府” 这一称谓总是鉴别那些掌权者的全局访问节点。

Structure

Implementations

单例模式的实现有两种:

  • Eager 饿汉式: 类加载就会导致该单实例对象被创建
  • Lazy 懒汉式: 类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建

Eager

public class Singleton {
//私有构造方法
private Singleton() {}

//在成员位置创建该类的对象
private static Singleton instance = new Singleton();

//对外提供静态方法获取该对象
public static Singleton getInstance() {
return instance;
}
}

Thread-safe Singleton with lazy loading

  1. static volatile variable
  2. make constructor be private
  3. static synchornized getInstance method
  4. make sure thread safe
public class Singleton {
// 1. static volatile variable
private static volatile Singleton instance;

// 2. make construcror be private
// 保证不能new,一旦可以new,就可以建造出很多instance,即不再是Singleton
private Singleton() {
}

// 3. static synchronized getInstance method
// static 保证在没有instance的情况下,可以调用该方法
public static Singleton getInstance() {
// 4. make sure thread safe
if (instance == null) { // 可能是多线程
synchronized(Singleton.class) { //保证只能进入一个线程
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}

Relations with Other Patterns

  • A Facade class can often be transformed into a Singleton since a single facade object is sufficient in most cases. 外观模式类通常可以转换为单例模式类, 因为在大部分情况下一个外观对象就足够了。
  • Abstract Factories, Builders and Prototypes can all be implemented as Singletons. 抽象工厂模式、 生成器模式和原型模式都可以用单例来实现。