模式说明

有一些对象,他们由多个部件构成,构成的方式相同,但每个部件在不同对象中可能有不同的特征细节。举例来说,无论是哪个品牌的电脑,都由CPU,显示器,硬盘内存,键盘等部件构成,只是对不同品牌不同型号的PC,部件的细节不同,例如苹果电脑的CPU是苹果自研的,联想电脑CPU是英特尔的。在客户端中完成对不同对象的建造,最直接的方式是分别声明声明他们,然后调用各自的建造动作来完成。这样的做法无法利用不同对象建造过程稳定且相同(只是细节不同)的特点,达不到代码复用的效果。针对这种场景,可以使用建造者模式来实现。

建造者模式提供一个抽象建造者类,类内定义了稳定的产品建造过程,即建造具体产品各部件的抽象方法。这样具体建造者继承抽象建造者类后,可以根据需要重写某些部件的建造方法。具体建造者类内持有一个产品类实例,用于保存建造完成后的产品,并通过他的getter的方法获取该产品的实例。展示产品细节的动作在产品类中完成。这就是所谓的将复杂对象的构造和表示分离,实际就是建造者类和产品类分离。至此,若客户端发起造,就可以声明一个具体建造类,并调用其建造过程(多个部件的build方法),但这样一来就对客户端暴露了建造过程,且加重了客户端的任务。所以另外设置一个指挥者类,该类只有一个produce方法,方法参数是具体建造者实例,传入该实例,在produce内部调用该实例建造各部件的方法。如此,客户端就只需要声明一个指挥者,再声明一个具体建造者,将具体建造者作为指挥者的produce方法参数,指挥者执行其produce完成建造。执行后需要查看得到的产品细节,再调用产品建造者的getProduce方法即可。

本示例以汽车生产为例,展示如何利用建造者模式来生产F1赛车和普通家用汽车。

结构

指挥者类
提供一个指挥生产的方法produce,传入建造者,其内调用建造者的建造方法。
抽象建造者类
提供建造产品各部件的抽象方法和一个返回产品的方法。
具体建造者类
继承抽象建造者类,并持有一个产品实例以供获取。实现产品各部分抽象建造方法和返回产品的抽象方法。
产品类
持有产品各部件的一个集合实例,有一个增加部件的add方法,一个用于展现组成部件的show方法。

代码演示

  1. package com.yukiyama.pattern.creation;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. /**
  5. * 建造者模式(生成器模式)
  6. */
  7. public class BuilderDemo {
  8. public static void main(String[] args) {
  9. // 声明一个指挥者
  10. Director director = new Director();
  11. // 声明一个具体建造者
  12. CarMaker carMaker = new F1CarMaker();
  13. // 指挥者执行produce方法,传入具体建造者执行建造
  14. director.produce(carMaker);
  15. // 通过建造者的get方法得到建造后的产品
  16. Car car = carMaker.getCar();
  17. // 产品调用show方法展示建造后的产品细节
  18. car.show();
  19. }
  20. }
  21. /**
  22. * 指挥者类
  23. * 提供一个指挥生产的方法produce,传入具体建造者,执行既定的建造产品的方法
  24. * 完成产品制造。
  25. */
  26. class Director{
  27. public void produce(CarMaker cm) {
  28. cm.buildWheels();
  29. cm.buildEngine();
  30. cm.buildSeats();
  31. }
  32. }
  33. /**
  34. * 抽象建造者类
  35. * 提供建造产品各部件的抽象方法和一个返回产品的方法。
  36. * 下例为一个抽象汽车制造者类。
  37. */
  38. abstract class CarMaker{
  39. public abstract void buildWheels();
  40. public abstract void buildEngine();
  41. public abstract void buildSeats();
  42. public abstract Car getCar();
  43. }
  44. /**
  45. * 具体建造者类
  46. * 继承抽象建造者类,并持有一个产品实例,实现产品各部分抽象建造方法和返回
  47. * 产品的抽象方法(返回其持有的产品实例)。
  48. * 下例是F1赛车制造者
  49. */
  50. class F1CarMaker extends CarMaker{
  51. private Car car = new Car();
  52. @Override
  53. public void buildWheels() {
  54. car.add("赛车轮胎");
  55. }
  56. @Override
  57. public void buildEngine() {
  58. car.add("赛车引擎");
  59. }
  60. @Override
  61. public void buildSeats() {
  62. car.add("赛车座椅");
  63. }
  64. @Override
  65. public Car getCar() {
  66. return car;
  67. }
  68. }
  69. /**
  70. * 具体建造者类
  71. * 按照该建造者的实际情况实现产品各部分建造方法和返回产品方法
  72. * 下例是家用车制造者
  73. */
  74. class HomeCarMaker extends CarMaker{
  75. private Car car = new Car();
  76. @Override
  77. public void buildWheels() {
  78. car.add("家用车轮胎");
  79. }
  80. @Override
  81. public void buildEngine() {
  82. car.add("家用车引擎");
  83. }
  84. @Override
  85. public void buildSeats() {
  86. car.add("家用车座椅");
  87. }
  88. @Override
  89. public Car getCar() {
  90. return car;
  91. }
  92. }
  93. /**
  94. * 要建造的产品类
  95. * 持有产品各部件的集合List<String>,定义一个add方法用于添加构件。另定义
  96. * 一个show方法用于展示建造的产品细节。
  97. */
  98. class Car{
  99. private List<String> parts = new ArrayList<>();
  100. public void add(String part) {
  101. parts.add(part);
  102. }
  103. public void show() {
  104. System.out.println(parts);
  105. }
  106. }