定义

当构造函数参数过多且需要进行校验时,使用建造者模式。作用:

  • 避免构造函数参数过多
  • 校验属性之间的依赖关系和约束条件
  • 隐藏set方法,构造不可变对象

结构

  1. 产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。
  2. 抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
  3. 具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
  4. 指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。

建造者模式(Builder Pattern) - 图1

实例

  1. public class ResourcePoolConfig {
  2. private String name;
  3. private int maxTotal;
  4. private int maxIdle;
  5. private int minIdle;
  6. private ResourcePoolConfig(Builder builder) {
  7. this.name = builder.name;
  8. this.maxTotal = builder.maxTotal;
  9. this.maxIdle = builder.maxIdle;
  10. this.minIdle = builder.minIdle;
  11. }
  12. //...省略getter方法...
  13. //我们将Builder类设计成了ResourcePoolConfig的内部类。
  14. //我们也可以将Builder类设计成独立的非内部类ResourcePoolConfigBuilder。
  15. public static class Builder {
  16. private static final int DEFAULT_MAX_TOTAL = 8;
  17. private static final int DEFAULT_MAX_IDLE = 8;
  18. private static final int DEFAULT_MIN_IDLE = 0;
  19. private String name;
  20. private int maxTotal = DEFAULT_MAX_TOTAL;
  21. private int maxIdle = DEFAULT_MAX_IDLE;
  22. private int minIdle = DEFAULT_MIN_IDLE;
  23. public ResourcePoolConfig build() {
  24. // 校验逻辑放到这里来做,包括必填项校验、依赖关系校验、约束条件校验等
  25. if (StringUtils.isBlank(name)) {
  26. throw new IllegalArgumentException("...");
  27. }
  28. if (maxIdle > maxTotal) {
  29. throw new IllegalArgumentException("...");
  30. }
  31. if (minIdle > maxTotal || minIdle > maxIdle) {
  32. throw new IllegalArgumentException("...");
  33. }
  34. return new ResourcePoolConfig(this);
  35. }
  36. public Builder setName(String name) {
  37. if (StringUtils.isBlank(name)) {
  38. throw new IllegalArgumentException("...");
  39. }
  40. this.name = name;
  41. return this;
  42. }
  43. public Builder setMaxTotal(int maxTotal) {
  44. if (maxTotal <= 0) {
  45. throw new IllegalArgumentException("...");
  46. }
  47. this.maxTotal = maxTotal;
  48. return this;
  49. }
  50. public Builder setMaxIdle(int maxIdle) {
  51. if (maxIdle < 0) {
  52. throw new IllegalArgumentException("...");
  53. }
  54. this.maxIdle = maxIdle;
  55. return this;
  56. }
  57. public Builder setMinIdle(int minIdle) {
  58. if (minIdle < 0) {
  59. throw new IllegalArgumentException("...");
  60. }
  61. this.minIdle = minIdle;
  62. return this;
  63. }
  64. }
  65. }
  66. // 这段代码会抛出IllegalArgumentException,因为minIdle>maxIdle
  67. ResourcePoolConfig config = new ResourcePoolConfig.Builder()
  68. .setName("dbconnectionpool")
  69. .setMaxTotal(16)
  70. .setMaxIdle(10)
  71. .setMinIdle(12)
  72. .build();

与工厂模式的区别

工厂模式是用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象。
建造者模式是用来创建一种类型的复杂对象,通过设置不同的可选参数,“定制化”地创建不同的对象。

一个生动的例子:顾客走进一家餐馆点餐,我们利用工厂模式,根据用户不同的选择,来制作不同的食物,比如披萨、汉堡、沙拉。对于披萨来说,用户又有各种配料可以定制,比如奶酪、西红柿、起司,我们通过建造者模式根据用户选择的不同配料来制作披萨。