规则1. 用静态工厂方法代替构造器
例子:
public class Example {
}
public class StaticFactory {
//valueOf/Of/getInstance/newIntance
private static volatile Example example = null;
public static Example newIntance(){
return new Example();
} public static Example getInstance(){
if (example == null) {
synchronized (Example.class) {
if (example == null) {
return new Example();
}
}
}
return example;
} public static void main(String[] args) {
Example example = StaticFactory.getInstance();
System.out.println(example.hashCode());
Example example1 = StaticFactory.newIntance();
Example example2 = StaticFactory.newIntance();
System.out.println(example1 == example2);
}
}
好处:(通过规则1,终于知道经常出现的getInstance()和newInstance()的区别)
1. 方法名有意义;
2. 可以创建新实例,也可以单例(控制对象的生产方式)
3. 可将多态应用在实例创建上
缺点:
1. 实例的构造方法为public/protected
2. 和普通静态方法一样
规则2. 用Builder实现多个参数的构造器
例子:
public class NutritionFacts { //required
private final int servingSize;
private final int servings;
//optional
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate; private NutritionFacts(Builder builder){
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
} public static class Builder{
//required
private int servingSize;
private int servings;
//optional(default)
private int calories = 0;
private int fat = 0;
private int sodium = 0;
private int carbohydrate = 0; public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
} public Builder calories(int calories){
this.calories = calories;
return this;
}
public Builder fat(int fat){
this.fat = fat;
return this;
}
public Builder sodium(int sodium){
this.sodium = sodium;
return this;
}
public Builder carbohydrate(int carbohydrate){
this.carbohydrate = carbohydrate;
return this;
} //build()
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
}
public static void main(String[] args) {
NutritionFacts nutritionFacts = new NutritionFacts.Builder(2,3)
.calories(12).carbohydrate(23).fat(1).sodium(8).build(); }
终于知道有些源码里出现静态内部类Builder的原理了。。
好处:
1. 避免构造函数有多个参数或者重载多个构造函数的情况
2. 如果想用JavaBean的形式解决,需要调用很多setter方法,容易出现线程不安全的问题
比如:
public class NutritionFactsSetter { private int servingSize;
private int servings;
private int calories;
private int fat; public int getServingSize() {
return servingSize;
}
public int getServings() {
return servings;
}
public int getCalories() {
return calories;
}
public int getFat() {
return fat;
}
public void setServingSize(int servingSize) {
this.servingSize = servingSize;
}
public void setServings(int servings) {
this.servings = servings;
} public void setCalories(int calories) {
this.calories = calories;
}
public void setFat(int fat) {
this.fat = fat;
}
public static void main(String[] args) {
NutritionFactsSetter factsSetter = new NutritionFactsSetter();
factsSetter.setCalories(0);
factsSetter.setServings(0);
factsSetter.setFat(20);
}
}
但是,通过Builder方式构建出的对象是不可改变的(在NutritionFacts类中,所有属性和方法以及构造函数都是private的),所以不存在线程不安全问题。
3. 一个Builder对象可以重复用来实例化对象。
4. 避免Class.newInstance()方法的异常处理情况
缺点:
1. 实例化语句显得有些冗长
规则3.