第1条:用静态工厂方法代替构造器
所谓静态工厂方法,实际上只是一个简单的静态方法,它返回的是类的一个实例。
使用静态工厂方法的优点有:
1)它与构造函数不同,它有名字,你可以把名字起的更易于阅读。
如果你想让2个构造函数拥有相同个数和类型的参数,这将是无法实现的;即使是2个不同类型的参数顺序倒置的,使用者也非常容易搞混乱。
例:一个类Complex(复数:包含实部和虚部)对它的构造可能有这样2种需求:
- 分别给出实数部和虚数部来构造之;
- 基于极坐标来构造(提供“半径”和“角度”)
那么很显然这两种构造方式,都是由2个float型参数的,对于构造函数将无能为力,而静态工厂方法可以从方法名来区别开,而且还带来了易于辨识的好处:
public class Complex {
private final float re;
private final float im;
private Complex(float re, float im){
this.re = re;
this.im = im;
}
public static Complex valueOf(float re, float im){
return new Complex(re, im);
}
public static Complex valueOfPolar(float r, float theta){
return new Complex((float)(r * Math.cos(theta)), (float)(r * Math.sin(theta)));
}
}
注意:用静态工厂方法代替构造函数后,构造函数就成了private的了,当然如果你希望同时也提供公有的构造函数也是可以的。
2)它与构造函数不同,在每次被调用时,不要求非得创建一个新的对象。
静态工厂方法能够为重复的调用返回相同对象,这有助于类总能控制在某个时刻哪些实例应该存在。这种类被称作实例受控的类
。
3)它与构造函数不同,它们可以返回原返回类型的任何子类型的对象
。
这样在选择返回类型时更具有灵活性,此外,使用这种静态工厂方法时,甚至要求客户端通过接口来引用被返回的对象,而不是通过它的实现类来引用被返回的对象。(详见64条)
4)静态工厂所返回的对象的类可以随着每次调用而发生变化,这取决于静态工厂方法的参数值。
只要是已声明的返回类型的子类型,都是允许的。返回对象的类也可能随着发行版本的不同而不同。例如EnumSet类没有公有的构造器,只有静态工厂方法。
该图为 EnumSet方法的部分截图
5)静态工厂方法返回的对象所属的类,在编写包含该静态工厂方法的类时可以不存在。
使用静态工厂方法的缺点有:
1)静态工厂方法主要缺点在于,类如果不含公有的或者受保护的构造器,就不能被子类化。
2)程序员很难发现他们。
下面是静态工厂方法的一些惯用名称:
Type 表示工厂方法所返回的对象类型,例如:
BufferedReader br = Files.newBufferedReader(path);
- Type ----- getType 和 newType 的简版,例如
List<Complaint> litany = Collections.list(legacyLitany);
Reference:
- 《Effective Java(第三版)》Chapter 2:创建和销毁对象
- TonyLian https://tonylian.iteye.com/blog/378830