Effective Java 第三版读书笔记——条款3:使用私有构造器或枚举类型来强制实现 singleton 属性

单例(singleton)就是一个只实例化一次的类。使类成为单例可能会使它的测试变得困难,因为除非它实现了作为其类型的接口,否则不可能用模拟实现来代替这个单例。下面是几种实现单例的方法:

使用 public field 方法

// Singleton with public final field
public class Elvis {
    public static final Elvis INSTANCE = new Elvis();
    private Elvis() { ... }
    public void leaveTheBuilding() { ... }
}

私有构造器只会被调用一次来初始化用 public static final 修饰的属性 INSTANCE。因为没有 publicprotected 的构造器,这里只会存在一个 Elvis 实例。

该方法的优点:

  • API 明确表示这个类就是一个单例。公共静态属性是 final 的,所以它总是包含相同的对象引用。
  • 这个方法很简单。

使用 static factory 方法

// Singleton with static factory
public class Elvis {
    private static final Elvis INSTANCE = new Elvis();
    private Elvis() { ... }
    public static Elvis getInstance() { return INSTANCE; }
    public void leaveTheBuilding() { ... }
}

所有对 Elvis.getInstance 的调用都返回相同的对象引用,并且不会创建其他的Elvis实例。

该方法的优点:

  • 可以方便地将类的实现改为非单例,并且用户代码不需要改变。
  • 可以编写一个泛型单例工厂。
  • 方法引用可以被用作 supplier,例如 Elvis::instance 等同于 Supplier<Elvis>

使用只有一个元素的枚举类型

// Enum singleton - the preferred approach
public enum Elvis {
    INSTANCE;
    public void leaveTheBuilding() { ... }
}

这个方法与 public field 方法相似,但是更加简洁。这个方法看起来有一点不自然,但它通常是实现单例的最好方法。

注意:如果单例必须继承 Enum 以外的父类(尽管可以声明一个 Enum 来实现接口),那么就不能使用这种方法。

猜你喜欢

转载自www.cnblogs.com/LeeFire/p/9921829.html