Builder Pattern

遇到多个构造器形参时要考虑用构建器

引言

遇到多个构造器时要考虑用构建器(builder)

重叠构造器(telescoping constructor)

  1. // Telescoping constructor pattern - does not scale well! - Pages 11-12
  2. /**
  3. * 营养成分表
  4. */
  5. public class NutritionFacts {
  6. private final int servingSize; // (mL) required
  7. private final int servings; // (per container) required
  8. private final int calories; // optional
  9. private final int fat; // (g) optional
  10. private final int sodium; // (mg) optional
  11. private final int carbohydrate; // (g) optional
  12. /**
  13. * 重叠构造器模式:提供第一个只有必要参数的构造器
  14. */
  15. public NutritionFacts(int servingSize, int servings) {
  16. this(servingSize, servings, 0);
  17. }
  18. /**
  19. * 重叠构造器模式:第二个构造器有一个可选参数
  20. */
  21. public NutritionFacts(int servingSize, int servings, int calories) {
  22. this(servingSize, servings, calories, 0);
  23. }
  24. /**
  25. * 重叠构造器模式:第三个构造器在第二个构造器的基础上,加一个可选参数
  26. */
  27. public NutritionFacts(int servingSize, int servings, int calories, int fat) {
  28. this(servingSize, servings, calories, fat, 0);
  29. }
  30. /**
  31. * 重叠构造器模式:以此类推
  32. */
  33. public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium) {
  34. this(servingSize, servings, calories, fat, sodium, 0);
  35. }
  36. /**
  37. * 重叠构造器模式:以此类推
  38. */
  39. public NutritionFacts(int servingSize, int servings, int calories, int fat, int sodium, int carbohydrate) {
  40. this.servingSize = servingSize;
  41. this.servings = servings;
  42. this.calories = calories;
  43. this.fat = fat;
  44. this.sodium = sodium;
  45. this.carbohydrate = carbohydrate;
  46. }
  47. public static void main(String[] args) {
  48. NutritionFacts cocaCola = new NutritionFacts(240, 8, 100, 0, 35, 27);
  49. }
  50. }

缺点:

① 当有许多参数的时候,客户端代码会很难编写,并且仍然较难以阅读。

② 如果读者想知道那些值是什么意思,必须很仔细地数着这些参数来探个究竟。如果客户端不小心颠倒了其中两个参数的顺序,编译器也不会出错,但是在程序运行时会出现错误行为。

JavaBeans模式

  1. // JavaBeans Pattern - allows inconsistency, mandates mutability - Pages 12-13
  2. public class NutritionFacts {
  3. // Parameters initialized to default values (if any)
  4. private int servingSize = -1; // Required; no default value
  5. private int servings = -1; // " " " "
  6. private int calories = 0;
  7. private int fat = 0;
  8. private int sodium = 0;
  9. private int carbohydrate = 0;
  10. public NutritionFacts() { }
  11. // Setters
  12. public void setServingSize(int val) {
  13. servingSize = val;
  14. }
  15. public void setServings(int val) {
  16. servings = val;
  17. }
  18. public void setCalories(int val) {
  19. calories = val;
  20. }
  21. public void setFat(int val) {
  22. fat = val;
  23. }
  24. public void setSodium(int val) {
  25. sodium = val;
  26. }
  27. public void setCarbohydrate(int val) {
  28. carbohydrate = val;
  29. }
  30. public static void main(String[] args) {
  31. // 调用一个无参构造器来创建对象,然后调用setter()方法来设置
  32. NutritionFacts cocaCola = new NutritionFacts();
  33. cocaCola.setServingSize(240);
  34. cocaCola.setServings(8);
  35. cocaCola.setCalories(100);
  36. cocaCola.setSodium(35);
  37. cocaCola.setCarbohydrate(27);
  38. }
  39. }

缺点:

① 无法保证一致性:JavaBean模式自身有着很严重的缺点,因为构造过程被分到了几个调用中,在构造过程中JavaBean可能处在不一致的状态。试图使用处于不一致状态的对象,将会导致失败,这种失败调试起来十分困难

② 阻止了把类做成不可变

Builder模式

  1. // Builder Pattern - Pages 14-15
  2. public class NutritionFacts {
  3. private final int servingSize;
  4. private final int servings;
  5. private final int calories;
  6. private final int fat;
  7. private final int sodium;
  8. private final int carbohydrate;
  9. /**
  10. * 注意是static修饰, 作为NutritionFacts的静态成员类
  11. * 详细的讨论请参考:
  12. * https://stackoverflow.com/questions/5007355/builder-pattern-in-effective-java
  13. */
  14. public static class Builder {
  15. // Required parameters
  16. private final int servingSize;
  17. private final int servings;
  18. // Optional parameters - initialized to default values
  19. private int calories = 0;
  20. private int fat = 0;
  21. private int carbohydrate = 0;
  22. private int sodium = 0;
  23. public Builder(int servingSize, int servings) {
  24. System.out.println("NutritionFacts.Builder init this[" + this + "]");
  25. this.servingSize = servingSize;
  26. this.servings = servings;
  27. }
  28. // builder的setter()方法返回builder本身,以便可以把调用链接起来
  29. public Builder calories(int val) {
  30. calories = val;
  31. return this;
  32. }
  33. public Builder fat(int val) {
  34. fat = val;
  35. return this;
  36. }
  37. public Builder carbohydrate(int val) {
  38. carbohydrate = val;
  39. return this;
  40. }
  41. public Builder sodium(int val) {
  42. sodium = val;
  43. return this;
  44. }
  45. /**
  46. * build()方法可以检验这些约束条件
  47. * 如果违反了任何约束条件build方法就应该抛出IllegalSelectorException
  48. */
  49. public NutritionFacts build() {
  50. return new NutritionFacts(this);
  51. }
  52. }
  53. /**
  54. * 注意这是private修饰的
  55. */
  56. private NutritionFacts(Builder builder) {
  57. servingSize = builder.servingSize;
  58. servings = builder.servings;
  59. calories = builder.calories;
  60. fat = builder.fat;
  61. sodium = builder.sodium;
  62. carbohydrate = builder.carbohydrate;
  63. }
  64. public static void main(String[] args) {
  65. // 不直接生成想要的对象,而是让客户端利用所有必要的参数调用NutritionFacts.Builder(int, int)创建一个builder对象
  66. // 然后客户端在builder对象调用类似于setter的方法,来设置每个相关的可选参数
  67. // 最后客户端调用无参的build()方法来生成不可变的对象NutritionFacts
  68. NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).calories(100).sodium(35).carbohydrate(27).build();
  69. NutritionFacts cocaCola2 = new NutritionFacts.Builder(240, 8).calories(100).sodium(35).carbohydrate(27).fat(7).build();
  70. }
  71. }

优点:
① Builder方式创建的对象,在调用 build() 方法之前是不会创建NutritionFacts 对象的,所有的属性设置都必须在 build() 方法之前,而且创建了NutritionFacts 对象后就不可以更改其属性了,这就保证了对象状态的唯一性,而且代码的可读性也提高了。

② 如果有些参数是必填的,可以加到 Builder 的构造函数中

缺点:

Builder模式的确也有自身不足,为了创建对象,必须先创建它的构建器,在某些十分注重性能的情况下,可能就成为问题了。

参考

时间: 2024-08-13 18:47:51

Builder Pattern的相关文章

建造者模式(Builder Pattern)

一. 建造者(Builder)模式 建造者模式(Builder)将复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示.在软件系统中,有时候面临一个复杂对象的创建工作,该对象通常由各个部分子对象用一定的算法构成,或者按一定的步骤组合而成:这些算法和步骤是稳定的,而构成这个对象的子对象却经常由于需求的变化而不断变化. 二.建造者模式的结构 建造者模式参与者: ◊ Builder:为创建一个Product对象的各个部件指定抽象接口: ◊ ConcreteBuilder ° 实现Builde

生成器模式(Builder Pattern)

一. 建造者(Builder)模式 建造者模式可以将一个产品的内部表象与产品的生成过程分割开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象. 对象性质的建造 有些情况下,一个对象会有一些重要的性质,在它们没有恰当的值之前,对象不能作为一个完整的产品使用.比如,一个电子邮件有发件人地址.收件人地址.主题.内容.附录等部分,而在最起码的收件人地址未被赋值之前,这个电子邮件不能发出. 有些情况下,一个对象的一些性质必须按照某个顺序赋值才有意义.在某个性质没有赋值之前,另一个性质则无法赋值.

.NET设计模式 第二部分 创建型模式(3)—建造者模式(Builder Pattern)

建造者模式(Builder Pattern) ——.NET设计模式系列之四 Terrylee,2005年12月17日 概述 在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成:由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法确相对稳定.如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变?这就是要说的建造者模式. 本文通过现实生活中的买

第4章 建造者模式(Builder Pattern)

原文 第4章 建造者模式(Builder Pattern) 定义 将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示,这样的设计模式被称为建造者模式. 实用范围 1 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时. 2 当构造过程必须允许被构造的对象有不同表示时. 角色 在这样的设计模式中,有以下几个角色: 1 builder:为创建一个产品对象的各个部件指定抽象接口. 2 ConcreteBuilder:实现Builder的接口以构造和装配该产品的各个部

Builder Pattern 在 Objective-C 中的使用

在说 Builder Pattern 之前,我们先来看看一个场景.假设我们要预定一个 iPhone 6,要 64G 的,金色的,用代码表述大概是这样 1 2 3 4 // PFX 是一个前缀,因为直接写 iPhone6 不符合类名大写的习惯,写成 IPhone6 更是怪异 ╮(╯▽╰)╭ PFXiPhone6 *iphone = [[PFXiPhone6 alloc] init]; iphone.storage = 64; iphone.color = [UIColor goldenColor]

深入浅出设计模式——建造者模式(Builder Pattern)

模式动机无论是在现实世界中还是在软件系统中,都存在一些复杂的对象,它们拥有多个组成部分,如汽车,它包括车轮.方向盘.发送机等各种部件.而对于大多数用户而言,无须知道这些部件的装配细节,也几乎不会使用单独某个部件,而是使用一辆完整的汽车,可以通过建造者模式对其进行设计与描述,建造者模式可以将部件和其组装过程分开,一步一步创建一个复杂的对象.用户只需要指定复杂对象的类型就可以得到该对象,而无须知道其内部的具体构造细节. 在软件开发中,也存在大量类似汽车一样的复杂对象,它们拥有一系列成员属性,这些成员

"围观"设计模式(9)--创建型之创建者模式(Builder Pattern)

生成器模式(英:Builder Pattern)是一种设计模式,又名:建造模式,是一种对象构建模式.它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象.----WIKIPEDIA 个人的理解: 建造者模式可以设置不同的属性或者行为,创建出不一样的对象.比如说生产汽车,假如有三个重要的工序,塑形.拼装.上色.那么可以通过创建者模式来设置,这三道工序中不同的车来说,三道工序可能就是不一样的.通过创建者模式来创建出对象的表现形式也自然就不一样.

C#设计模式之四建造者模式(Builder Pattern)【创建型】

原文:C#设计模式之四建造者模式(Builder Pattern)[创建型] 一.引言 今天我们要讲讲Builder模式,也就是建造者模式,当然也有叫生成器模式的,英文名称是Builder Pattern.在现实生活中,我们经常会遇到一些构成比较复杂的物品,比如:电脑,它就是一个复杂的物品,它主要是由CPU.主板.硬盘.显卡.机箱等组装而成的.手机当然也是复杂物品,由主板,各种芯片,RAM 和ROM  摄像头之类的东西组成.但是无论是电脑还是手机,他们的组装过程是固定的,就拿手机来说,组装流水线

建造者模式(Builder Pattern)

模式定义 造者模式(Builder Pattern):将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. UML类图 Builder:抽象建造者 ConcreteBuilder:具体建造者 Director:指挥者 Product:产品角色 代码结构 public static class BuilderApp { public static void Run() { Director director = new Director(); Builder b1 = new