1.静态工厂方法

当一个类需要多种方式来进行初始化的时候,我们需要构建编写多个该类的构造函数,需要定义不同的参数类型,参数个数来满足不同场景下该类的初始化。然而当一些特定业务需求时,参数个数和类型都是一样的,而代表的业务却不同的时候,使用构造函数来初始化类就很难了。

静态工厂方法可以为类的构造函数进行命名和进行不同参数类型创建的区分。

例如一个随机数的创建类:

1
2
3
4
public RandomIntGenerator(int min) {
this.min = min;
this.max = Integer.MAX_VALUE;
}

到目前为止,一切正常。但是,我们同样要提供一个构造函数设置一个最大值,然后产生一个介于Integer.MIN_VALUE和最大值的整数。我们添加个构造函数如下:

1
2
3
4
public RandomIntGenerator(int max) {
this.min = Integer.MIN_VALUE;
this.max = max;
}

如果你这样做了,将会出现编译错误:Duplicate method RandomIntGenerator(int) in type RandomIntGenerator,问题在于构造器没有名字。因此,一个类仅有一个特定方法签名的构造器。同样的,你不能定义方法签名相同的(返回值、名称、参数类型及个数均相同)两个方法。这就是为什么当我们试着添加构造器RandomIntGenerator(int max) 时,会得到上述的编译错误,原因是我们已经有一个构造器 RandomIntGenerator(int min)。

将静态工厂应用到RandomIntGenerator类,得到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class RandomIntGenerator {
private final int min;
private final int max;
private RandomIntGenerator(int min, int max) {
this.min = min;
this.max = max;
}
public static RandomIntGenerator biggerThan(int min) {
return new RandomIntGenerator(min, Integer.MAX_VALUE);
}
public static RandomIntGenerator smallerThan(int max) {
return new RandomIntGenerator(Integer.MIN_VALUE, max);
}
}

2.构建器

主要是解决当初始化类时对类的可选参数的扩展,使用静态工厂和构造函数都不能很好的解决这个问题。往往有时候采用重叠构造器的模式(对多参数时不可控)或者使用Javabeans(现成不安全),但当可选参数条目越来越多的时候,代码的重复的过多并且可用性不强。

构建器示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public static class Builder {
//required parameters
private final int servingSize;
private final int servings;
//Optional parameters - initialized to default values
private int calories;
private int fat;
private int sodium;
private int carbohydrate;
public Builder(int servingSize, int servings){
this.servingSize = servingSize;
this.servings = servings
}
public Builder calories(int val){
calories = val;
return this;
}
public Builder fat(int val){
fat = val;
return this;
}
public Builder sodium(int val) {
sodium = val;
return this;
}
public Builder carbohydrate(int val){
carbohydrate = val;
return this;
}
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder){
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
}
NutritionFacts juice = new NutritionFacts.Builder(240, 8).
calories(100).sodium(35).carbohydrate(27).build();

3.私有构造器强化单例

目前三中方式:

3.1 把构造器私有化,内部实例化一份实例对外暴露

1
2
3
4
5
public class Melon {
public static final Melon INSTANCE = new Melon();
private Melon(){}
}

3.2 构造器私有化,将内部成员示例变成静态工厂方法

1
2
3
4
5
6
7
8
9
public class Melon{
private static final Melon INSTANCE = new Melon();
private Melon(){}
public static Melon getInstance(){
return INSTANCE;
}
}

3.3 编写一个包含单个元素的枚举类型,可自动进行序列化机制。(推荐)

1
2
3
4
public enum Melon{
INSTANCE;
}