在由许多不同对象实现的接口上使用静态工厂方法是否更好?

Is it better practice to use static factory methods over an interface implemented by many different objects?

似乎您既可以使用静态工厂方法,也可以使用许多对象实现的接口来使用户(或您自己)更容易实例化正确的对象。

因此,这似乎是一个决定,一方面,拥有具有许多静态工厂方法的巨型对象,或者另一方面,拥有一个由许多不同对象实现的接口,如此之多,以至于变得困难让用户知道从哪里开始。

示例 2:具有许多静态工厂方法的 class:

FooObj foo01 = FooObj.bigFoo();
FooObj foo02 = FooObj.smallFoo();

示例 1:具有许多 class 实现该接口的接口。

Foo foo1 = new BigFoo();
Foo foo2 = new SmallFoo();

是公开构造函数 public 还是隐藏它们只公开一个 工厂方法 然后决定如何以及何时实例化 class是一个设计决定,取决于你是否想在实例化之前做逻辑,或者实例化哪个具体 class 的决定是否不由调用者决定。

引用维基百科:

the factory method pattern is a creational pattern that uses factory methods to deal with the problem of creating objects without having to specify the exact class of the object that will be created. This is done by creating objects by calling a factory method—either specified in an interface and implemented by child classes, or implemented in a base class and optionally overridden by derived classes—rather than by calling a constructor.

在 Java 中发生这种情况的一个示例是 Calendar class,它是 abstract 并且不提供 public 构造函数。相反,它提供了一个 getInstance() 方法,该方法执行一些逻辑来确定哪个是为调用者实例化的正确具体实例。

你所想的问题在名著中得到了解答。 Effective Java,第 3 版,作者 Joshua Bloch。请注意,Joshua Bloch 也是多个 Java SE classes 的开发者。

引自书中:

ITEM 1: CONSIDER STATIC FACTORY METHODS INSTEAD OF CONSTRUCTORS

Joshua 给出了使用静态工厂方法代替构造函数的以下原因

  • One advantage of static factory methods is that, unlike constructors, they have names
  • A second advantage of static factory methods is that, unlike constructors, they are not required to create a new object each time they’re invoked.
  • A third advantage of static factory methods is that, unlike constructors, they can return an object of any subtype of their return type.
  • A fourth advantage of static factories is that the class of the returned object can vary from call to call as a function of the input parameters.
  • A fifth advantage of static factories is that the class of the returned object need not exist when the class containing the method is written.

Joshua 还讲述了静态工厂方法的问题

  • The main limitation of providing only static factory methods is that classes without public or protected constructors cannot be subclassed.

  • A second shortcoming of static factory methods is that they are hard for programmers to find.

Java.util.Collections 可以看作静态工厂方法的一个例子。引自书中

For example, the Java Collections Framework has forty-five utility implementations of its interfaces, providing unmodifiable collections, synchronized collections, and the like. Nearly all of these implementations are exported via static factory methods in one noninstantiable class (java.util.Collections). The classes of the returned objects are all nonpublic.

作者进一步回应了您的想法

The Collections Framework API is much smaller than it would have been had it exported forty-five separate public classes, one for each convenience implementation. It is not just the bulk of the API that is reduced but the conceptual weight: the number and difficulty of the concepts that programmers must master in order to use the API. The programmer knows that the returned object has precisely the API specified by its interface, so there is no need to read additional class documentation for the implementation class. Furthermore, using such a static factory method requires the client to refer to the returned object by interface rather than implementation class, which is generally good practice (Item 64).

Java 由于 Joshua Bloch 提出的优点,标准库广泛使用了静态工厂方法。另一个例子是 java.lang.Boolean class 中的 valueOf 函数。 valueOf 静态工厂方法漂亮地一次又一次地为您提供相同的对象(基本上是缓存)

public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
public static Boolean valueOf(boolean b) {
    return (b ? TRUE : FALSE);
}