获取一个类的实例的传统方法是使用公开的构造器,除此之外,一个类还可以提供公开的静态工厂方法(static factory method)来返回它的实例。例如 Boolean
类中的 valueOf
方法,这个方法将基本类型 boolean
转换为一个 Boolean
对象的引用:
public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
}
注:静态工厂方法与设计模式中的工厂方法不同。
与构造器不同,静态工厂方法拥有自己的名字。考虑一个场景: BigInterger
类的一个构造器 BigInterger(int, int, Random)
可能返回一个素数,然而传统的构造器不能很直观地表达出来,我们可以用一个静态工厂方法 BigInteger.probablePrime
使表达变得更清晰。
此外,如果一个类需要几个参数类型相同的构造器,它只能打乱参数的顺序来进行区别,这使得类的构造变得十分困难。此时可以考虑使用静态工厂方法,这些方法拥有相同的参数类型,但你可以赋予它们精心挑选的名字,使它们的区别变得明显。
当静态工厂方法被调用时,它们不需要每一次都创建一个新的对象。如开篇的 Boolean.valueOf(boolean)
所示,这个方法从来不创建对象,它只是返回 Boolean
类中已经创建的对象:
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
这有效地提升了程序的性能。这一技巧与设计模式中的享元模式(Flyweight)十分相似。
静态工厂方法可以返回其返回类型的任何子类的对象。一个可能的应用场景:API 可以返回对象,而不需要将它们的类公之于众,以这种方式隐藏实现类将使这个 API 变得十分紧凑。这个技术适合于基于接口的框架(interface-based frameworks)。
随着输入参数的不同,同一个静态工厂方法可以返回不同的子类。例如 EnumSet
类:
public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
Enum<?>[] universe = getUniverse(elementType);
if (universe == null)
throw new ClassCastException(elementType + " not an enum");
if (universe.length <= 64)
return new RegularEnumSet<>(elementType, universe);
else
return new JumboEnumSet<>(elementType, universe);
}
当底层枚举类型的元素不超过64个时,返回 RegularEnumSet
,超过64个则返回 JumboEnumSet
。
在编写包含静态方法的类时,返回对象的类不需要存在。这种灵活的静态工厂方法构成了服务提供者框架(service provider frameworks)的基础,比如Java的数据库连接 API(JDBC)。
public
或 protected
构造器的类不能被继承(子类化)。这也可能因祸得福:它鼓励程序员使用组合而不是继承。from
:一个类型转换方法,接受一个参数并返回这个类型的相应实例。
Date d = Date.from(instant);
of
:一个聚合方法,接受多个参数、将它们合并在一起并返回这个类型的相应实例。
Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING);
valueOf
:from
和 to
的更为详细的替代方式。
BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);
instance
或 getInstance
:返回一个实例,该实例由其参数(如果有的话)描述,但不能说具有相同的值。
StackWalker luke = StackWalker.getInstance(options);
create
或 newInstance
:与 instance
或 getInstance
类似,除了该方法保证每个调用返回一个新的实例。
Object newArray = Array.newInstance(classObject, arrayLen);
getType
:与 getInstance
类似,当工厂方法在不同的类中时使用。Type 是工厂方法返回对象的类型。
FileStore fs = Files.getFileStore(path);
newType
:与 newInstance
类似,当工厂方法在不同的类中时使用。Type 是工厂方法返回对象的类型。
BufferedReader br = Files.newBufferedReader(path);
type
: getType
和 newType
的简洁版。
List<Complaint> litany = Collections.list(legacyLitany);
Effective Java 第三版读书笔记——条款1.考虑使用静态工厂方法替代构造器
原文:https://www.cnblogs.com/LeeFire/p/9911735.html