- 静态工厂方法
解释:类中定义共有的静态方法返回类的实例(可以是该类本身,也可以是别的类)。
优势:
- 静态工厂方法可以有名称
- 静态工厂方法与构造器不同的优势,不必在每次调用它们的时候都创建一个新对象
- 静态工厂方法可以返回原返回类型的任何子类型
- 静态工厂方法所返回的对象的类,可以随着每次调用发生变化
- 方法返回的对象所属的类,在编写包含该静态工厂方法的类时可以不存在
其中第2~5点有些啰嗦,牵强附会。构造器的本意就是构造类的实例,因此,构造器的返回类型就被限定了,也不能算什么缺憾。而静态工厂方法其实就是普通的静态方法,当然可以返回任意类型。不过相对于构造器生成实例,静态工厂方法提到的第一点优势--可以有名称实在比较好用。
对于下面这个类,如果再想写入参为一个int型的初始化bb构造函数是不可以的了,因为函数类型时根据入参类型,而不是入参名区分的。
public Class A{
int aa = 0;
int bb = 0;
public A(int tmp){
aa = tmp;
bb = 0;
}
}
因此可以使用静态工厂方法,直接通过不同的函数命令来实例化类,如下:
public Class A{
int aa = 0;
int bb = 0;
private static final DEAINSTANCE = new A(0,0);
private A(int aa, int bb){
aa = aa;
bb = bb;
}
//该静态方法可以用来修改aa的值
public static A newAwithaa(int aa){
retuan new A(aa, 0);
}
//该静态方法可以用来修改bb的值
public static A newAwithbb(int bb){
retuan new A(0, bb);
}
//该静态方法获取一个默认的实例,而不重新构造新的对象
public static A getInstance(){
return DEAINSTANCE;
}
}
下面列出静态工厂方法的惯用名称:
from--类型转换方法,从A实例转成B实例
of-----聚合方法 ,聚合多个参数,生成新的实例
valueOf---比from和of更烦琐的替代方法
instance/getInstance----根据入参(如果有)返回不同的实例
create/newInstance-----根据入参(如果有)返回不同新的实例
getType----类似getInstance
newType---类似newInstance
- 构建器
背景:遇到多个构造器参数时,一般的重叠构造器模式会导致混乱。构造器函数名称相同,仅入参不同,如果有5个参数,那么该模式的构造器将至少有五个,使用时很混乱,不方便。使用javaBeans模式虽然可以一定程度解决这种混乱问题,但是割裂了实例的初始化过程,可能在第一次和第二次使用同一个实例之间,调用了set某个参数的方法,导致实例实际上不同;并且JavaBeans模式使得把类做成不可变的可能性不复存在。
解释:构建器不直接生成想要的对象,而是让客户端利用所有必要的参数调用构造器(或者静态工厂),得到一个builder对象。然后客户端在builder对象上调用类似于setter的方法,来设置每个相关的可选参数。最后,客户端调用无参的build方法生成通常是不可变的对象。
以下代码是一个builder模式的示例:
Builder是待构建的类的一个内部类,Builder类具有该类的所有属性,每个属性都提供了一个方法进行设置,并且设置方法的返回类型为Builder。这一特点使得可以链式调用各个设置函数。在链式的末端,使用一个无参的build函数构建该类,build函数返回一个类的构造函数,构造函数的入参为Builder的一个实例。
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
public static class Builder {
private final int servingSize;
private final int servings;
private int calories = 0;
public Builder(int servingSize, int servings){
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val){
this.calories = val;
return this;
}
public NutritionFacts build(){
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder){
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
}
public static void main(String[] args) {
NutritionFacts cocaCola = new Builder(5, 20).calories(5).build();
}
}
- 私有构造器
- 优先考虑依赖注入