Item 1:考虑使用静态工厂方法替代构造方法
注意:这里的静态工厂方法
static factory method
和设计模式中的工厂方法模式Factory Method pattern
不等价。
优点
有方法名,便于用于阅读和理解
更加语义化。
特别是有多个构造函数时,容易错误的调用。静态工厂方法有方法名,很容易辨识。
不必每次调用时都创建一个新对象
允许不可变的类
immutable classes
使用预先构建的实例。构造时缓存实例,避免创建不必要的重复对象。
可以提高性能,尤其是那种创建他们非常昂贵的情况(耗性能)下。
与构造方法不同,可以返回原类型的子类对象
这个子类可以是隐藏的,即非公开的内部类或包私有类。
例子:java.util.Collections
里有很多内部的集合。
返回对象所属类可以根据输入参数变化而变化
举例:EnumSet
类的静态工厂方法noneOf
方法。如果大多数枚举类型具有64个或更少的元素,静态工厂将返回一个RegularEnumSet
实例, 返回一个long
类型;如果枚举类型具有六十五个或更多元素,则工厂将返回一个JumboEnumSet
实例,返回一个long
类型的数组。
这两个实现类的存在对于客户是不可见的。
返回对象所属类在编写含该静态工厂方法的类时可以不必存在
SPI。静态构造方法返回的是该子类对象,但接受的是接口。
举例:JDBC
缺点
只提供静态工厂方法,则没有public/protected构造方法的类不能被子类化
通过继承创建子类。由于子类的构造中要调用父类的构造。因此父类没有public/protected的构造方法则无法子类化。
可以通过组合实现。
很难让开发者找到
不能像构造方法那么突出。可以通过Javadoc标注。
静态工厂方法常用命名
from
:类型转换方法。接受单个参数并返回此类型的相应实例。1
Date d = Date.from(instant);
of
:聚合方法,接受多个参数并返回该类型的实例。1
Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING)
valueOf
:from
和of
更为详细的替代方法。1
BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);
instance
或者getInstance
:返回一个由其参数(如果有的话)描述的实例,但不能说它具有相同的值。1
StackWalker luke = StackWalker.getInstance(options);
create
或者newInstance
:与instance
或getInstance
类似,除了该方法保证每个调用返回一个新的实例。1
Object newArray = Array.newInstance(classObject, arrayLen);
区别:
create
或者newInstance
每次调用都返回新的实例。instance
或者getInstance
不一定。getType
:和getInstance
类似,在工厂方法处于不同的类中的时候使用。1
FileStore fs = Files.getFileStore(path);
newType
:和newInstance
类似,在工厂方法处于不同的类中的时候使用。1
BufferedReader br = Files.newBufferedReader(path);
type
:getType
和newType
简洁的替代方式。1
List<Complaint> litany = Collections.list(legacyLitany);