Effective Java读书笔记之遇到多个构造器参数时考虑用构建器(builder)

    如果类的构造器或者静态工厂中具有多个参数,设计这种类时,Builder模式就是中不错的选择,特别是当大多参数都是可选的时候 。与使用传统的 重叠构造器模式相比,使用Builder模式的客户端代码将更易于阅读和编写,构建器也比 JavaBeans更安全。

eg. 

    1,针对多参数使用重叠构造器模式(telescoping contructor)
package cn.evansung;

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 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;
	}
}
NutritionFacts cocaCola = new NutritionFacts(240, 8, 100, 0, 35, 27);
重叠构造器模式可行,但是当有许多参数的时候,客户端代码会很难编写,并且仍然难以阅读。(例如一长串类型类型相同的参数会导致一些微妙的错误。如果客户端不小心颠倒了其中两个参数的顺序,编译器可能不会出错,但是程序在运行时会 出现错误的行为)
    2,针对多参数使用JavaBeans模式
package cn.evansung;

public class NutritionFacts {
	private int servingSize;
	private int servings;
	private int calories;
	private int fat;
	private int sodium;
	private int carbohydrate;
	
	public NutritionFacts() {}
	
	//Setters
	public void setServingSize(int val) { servingSize = val; }
	public void setServings(int val) { servings = val; }
	public void setCalories(int val) { calories = val; }
	public void setFat(int val) { fat = val; }
	public 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);
这种模式弥补了重叠构造器模式的不足,通过调用 一个无参构造器来创建对象,然后 调用setter方法来设置每个必要的参数,以及每个相关的可选参数。但是这个模式有个严重的缺点。因为构造过程被分到了几个调用中,在构造过程中JavaBean可能处于不一致的状态。类无法仅仅通过检验构造器参数的有效性来保证一致性。试图使用处于不一致状态的对象,将会导致失败,这种失败与包含错误的代码大相径庭,因此调试起来十分困难。
   
    3,针对多参数使用Builder模式
package cn.evansung;

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 param
		private final int servingSize;
		private final int servings;
		
		//optinal param
		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 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 cocaCola = new NutritionFacts.Builder(240, 8).
			calories(100).sodium(35).carbohydrate(27).build();
所有默认参数值都单独放在一个地方。builder的setter方法返回builder本身,以便可以吧调用链接起来。Builder模式十分灵活,可以利用单个builder构建多个对象。builder的参数可以在创建对象期间进行调整,也可以随着不同的对象而改变。Builder模式也有不足。为了创建对象 ,必须先创建它的构造器。虽然创建构造器的开销在实践中可能不那么明显,但是在某些十分注重性能的情况下,可能就成了问题。Builder模式比重叠构造器模式更加冗长,因此它只有在有很多参数的时候才使用,比如4个或者更多个参数。

总结,如果类的构造器或者静态工厂中具有多个参数,设计这种类时,Builder模式就是种不错的选择,特别是当大多数参数都是可选的时候。与使用传统的重叠构造器模式相比,使用Builder模式的客户端代码将更易于阅读和编写,构造器也比JavaBeans更加安全。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值