使用Builder模式代替来创建实例
2015-04-06 15:09
288 查看
引入:
考虑有这样一个类的设计,它用来表示包装食品外面的营养标签,包含以下内容:
每罐的含量(servingSize)
营养品的种类(servings)
卡路里(calories)
脂肪含量(fat)
钠含量(sodium)
糖含量(carbohydrate)。
其中前两个是必须的,后面几项是可选的。
对于这样的类,应该用哪种构造方法或者静态方法来编写呢?一种常用的方法是采用重叠构造器(telescoping constructor)。例如:
这种方法可行,但是当有许多参数时,客户端代码会很难编写,并且较难阅读。如果读者想明白这些值是什么意思,需要仔细的数着参数来探个究竟。一长串类型相似的参数会导致一些微妙的错误,如果客户端不小心颠倒了其中两个参数的顺序,编译器不会报错,但在程序运行时会出现错误的行为。
方案二
调用一个无参的构造方法来创建对象,然后调用setter方法来设置每个必要的参数,以及每个必要的参数。
这种模式弥补了重叠构造器模式的不足。就是创建实例容易,这样产生的代码也容易阅读。
NutritionFacts cocaCola = new NutritionFacts();
cocaCola.setServingSize(240);
cocaCola.setServings(8);
cocaCola.setCalories(100);
cocaCola.setSodium(35);
cocaCola.setcarbohydrate(27);
优缺点:
因为构造过程被分到了几个调用中,类的对象可能处于不一致的状态。类无法通过检验构造器参数的有效性来保证一致性。试图使用处于不一致状态的对象,将会导致失败,而且,这种模式阻止了把类做成不可变的可能。
方案三(Builder模式)
Builder模式可以有多个可变参数,使用单独的方法来设置每个参数。简言之,如果类的Constructor或静态工厂方法中有多个参数,就可以考虑使用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模式。
相关文章推荐
- [代码实例][gtk+]使用builder创建UI
- 设计模式——创建型之使用建造者模式(Builder Pattern)灵活自由创建你的对象(一)
- 抽象工厂模式:简单工厂模式、工厂方法模式对比;在工厂方法模式中使用反射创建对象实例
- 使用builder模式创建Websocket客户端
- Ruby设计模式编程中使用Builder建造者模式的实例
- 设计模式--原型模式--Spring框架中使用原型模式创建新的bean实例
- 需要使用单一实例合需要应用单例模式的区别
- 为Windows应用创建简单的异步调用模式(附实例代码)
- 使用 MyEclipse 插件创建 Hibernate + Struts 连接oracle实例(动画)
- 使用CallByName“代替”模式窗口。
- 利用CVSNT在Eclipse中使用CVS--3.创建一个CVS实例
- Builder模式实例分析(C语言版)
- 一个使用泛型堆栈模块创建的两个容纳不同类型数据的实例
- 利用CVSNT在Eclipse中使用CVS--3.创建一个CVS实例
- OleDbCommandBuilder 使用实例
- 如何使用 IBM Rational Software Architect 创建复合模式
- 使用ATL创建COM程序实例
- 使用 MyEclipse 插件创建 Hibernate + Struts 实例(动画)
- 实例讲解.NET中资源文件的创建与使用
- 实例讲解.NET中资源文件的创建与使用