第二章 创建和销毁对象
1.考虑用静态工厂方法代替构造器
优势:
- 有名称,易于理解
- 可以重复利用对象,避免创建重复的对象
- 可以返回原返回类型的任何子类型对象
2.遇到多个构造器参数时要考虑用构建器
三种模式:
1. 构造器模式
- 当很多参数的时候,难编写,难阅读
2. JavaBeans模式
- 调用无参构造器创建对象,然后调用setter方法赋值
- 弥补构造器模式的缺点,创建对象容易,易阅读
- set过程被分到几个调用中,JavaBean可能处于不一致状态,需要额外保证线程安全
3. Builder模式
- 客户端利用所有必要的参数调用构造器得到builder对象,然后客户端在builder对象上调用类似setter的方法,来设置可选的参数,最后客户端调用无参的build方法生成不可变对象。
示例
// Builder Pattern - Pages 14-15
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 = 0;
private int fat = 0;
private int carbohydrate = 0;
private int sodium = 0;
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 carbohydrate(int val)
{ carbohydrate = val; return this; }
public Builder sodium(int val)
{ sodium = 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;
}
public static void main(String[] args) {
NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).
calories(100).sodium(35).carbohydrate(27).build();
}
}
3. 用私有构造器或枚举类型强化singleton属性
Singleton指仅被实例化一次的类
包含单个元素的枚举类型也可以实现Singleton
public enum Elvis { INSTANCE; public void leaveTheBuilding() {...} }
4. 通过私有构造器强化不可实例化的能力
- 例如:java.util.Arrays,java.util.Collections
- 企图通过将类做成抽象类来强制该类不可被实例化,这是行不通的。该类可以被子类化,且子类可以被实例化,这样做甚至会误导用户以为该类是为了继承而设计。