使用Builder模式代替来创建实例

引入:

考虑有这样一个类的设计,它用来表示包装食品外面的营养标签,包含以下内容:

每罐的含量(servingSize)

营养品的种类(servings)

卡路里(calories)

脂肪含量(fat)

钠含量(sodium)

糖含量(carbohydrate)。

其中前两个是必须的,后面几项是可选的。

对于这样的类,应该用哪种构造方法或者静态方法来编写呢?一种常用的方法是采用重叠构造器(telescoping constructor)。例如:

public NutritionFacts(int servingSize, int servings) {
    this(servingSize,servings,0);
}
public NutritionFacts(int servingSize, int servings,
        int calories) {
    this(servingSize,servings,calories,0);
}
public NutritionFacts(int servingSize, int servings,
        int calories, int fat) {
    this(servingSize,servings,calories,fat,0);
}
public NutritionFacts(int servingSize, int servings,
        int calories, int fat, int sodium) {
    this(servingSize,servings,calories,fat,sodium,0);
}
public NutritionFacts(int servingSize, int servings,
        int calories, int fat, int sodium, int carbohydrate) {
    this. servingSize = servingSize;
    this. servings = servings;
    this.calories = calories;
    this.fat = fat;
    this.sodium = sodium;
    this.carbohydrate = carbohydrate;
}

    这种方法可行,但是当有许多参数时,客户端代码会很难编写,并且较难阅读。如果读者想明白这些值是什么意思,需要仔细的数着参数来探个究竟。一长串类型相似的参数会导致一些微妙的错误,如果客户端不小心颠倒了其中两个参数的顺序,编译器不会报错,但在程序运行时会出现错误的行为。

方案二

调用一个无参的构造方法来创建对象,然后调用setter方法来设置每个必要的参数,以及每个必要的参数。

public class NutritionFacts {
    private int servingSize = -1;
    private int servings = -1;
    private int calories = 0;
    private int fat = 0;
    private int sodium = 0;
    private int carbohydrate = 0;

    public NutritionFacts() {}

    //setters
    public void setServingSize(int val) {servingSize = val;}
    public void setServings(int val){servings = val;}
    public void setCalories(int val){calories = val;}
    pubic void setSodium(int val) {sodium = val;}
    public void setCarbohydrate(int val){carbohydrate = val;}
}

这种模式弥补了重叠构造器模式的不足。就是创建实例容易,这样产生的代码也容易阅读。

NutritionFacts cocaCola = new NutritionFacts();

cocaCola.setServingSize(240);

cocaCola.setServings(8);

cocaCola.setCalories(100);

cocaCola.setSodium(35);

cocaCola.setcarbohydrate(27);

优缺点:

因为构造过程被分到了几个调用中,类的对象可能处于不一致的状态。类无法通过检验构造器参数的有效性来保证一致性。试图使用处于不一致状态的对象,将会导致失败,而且,这种模式阻止了把类做成不可变的可能。

方案三(Builder模式)

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;

    pubic static class Builder{
        private final int servingSize;
        private final int servings;
    
        private int calories = 0;
        private int fat = 0;
        private int carbohydrate = 0;
        private int sodium = 0;

        pubic Builder(int servingSize, int servings) {
            this.servingSize = servingSize;
            this.servings = servings;
        }
        public Builder calories(int val) {
	    this.calories = val;
	    return this;
        }
       public Builder fat(int val) {
           this.fat = val;
           return this;
       }
       public Builder carbohydrate(int val) {
            this.carbohydrate = val;
            return this;
       }	
       public Builder sodium(int val) {
            this.sodium = val;
            return this;
       }
       public NutritionFacts build() {
           return new NutritionFacts(this);
       }
    }
    //私有Constructor表明创建NutritionFacts对象时,只能通过Builder对象的build()方法。
    private NutritionFacts(Builder builder) {
	serviceSize = builder.serviceSize;
	servings = builder.servings;
		
	calories = builder.calories;
	fat = builder.fat;
	sodium = builder.sodium;
	carbohydrate = builder.carbohydrate;
    }
    //test case.
    public static void main(String[] args) {
        NutritionFacts cocaCola = new NutritionFacts.Builder(240,8).calories(100).sodium(35)
                .carbohydrate(27).build();
    }
}

Builder模式可以有多个可变参数,使用单独的方法来设置每个参数。简言之,如果类的Constructor或静态工厂方法中有多个参数,就可以考虑使用Builder模式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值