builder 模式

场景

  • 构造一个复杂的对象,很多的属性,有些属性构造的时候需要做一些校验,格式转换

构造器是一种非常棒,非常实用,非常常用的设计模式;

常见于在构建一个复杂的对象,或者是构建一个复杂的表达式的时候,在开源框架中有大量广泛的运用;

用构造器模式的最大好处是啥?
复杂对象的构建过程太复杂了,里面可能包含一些业务逻辑,比如值检查,格式转换之类的。如果每个客户端都自己手动去完成构建的话,那么大量的冗余代码是一个;另外一个,如果我们要改变对象的构建过程的实现,可以就在构造器中一个地方修改即可,对于调用方完全透明;最后,如果我们要完全替换掉以前的 builder 实现的话,那么完全可以在工厂里替换一个实现,还跟简单工厂模式结合起来使用了;
image.png

  1. package com.example.designpattern.builder;
  2. import java.util.Arrays;
  3. public class BuilderPatternDemo {
  4. public static void main(String[] args) {
  5. Director director = new Director(new ConcreteBuilder());
  6. Product product = director.build("值1","值2","值3");
  7. System.out.println(product);
  8. // 好处1:通过builder接口将复杂构建步骤拆分成了多个部分,代码逻辑清晰,维护性和扩展性都很好
  9. // 好处2:将对象构建的过程,封装在了director里面,director来基于builder进行构建,构建逻辑修改,不需要修改很多地方
  10. // 好处3:相对于工厂,有一个很好的抽象设计,director和builder
  11. }
  12. public interface Builder {
  13. void field1(String value);
  14. void field2(String value);
  15. void field3(String value);
  16. Product create();
  17. }
  18. public static class ConcreteBuilder implements Builder{
  19. public static Product product = new Product();
  20. public void field1(String value) {
  21. System.out.println("在设置field1之前进行复杂的校验逻辑");
  22. product.setField1(value);
  23. }
  24. public void field2(String value) {
  25. System.out.println("在设置field2之前进行复杂的数据格式转化逻辑");
  26. product.setField2(value);
  27. }
  28. public void field3(String value) {
  29. System.out.println("在设置field3之前进行复杂的数据处理逻辑,跟其他对象的数据进行关联");
  30. product.setField3(value);
  31. }
  32. public Product create() {
  33. return product;
  34. }
  35. }
  36. /**
  37. * director是面向builder的接口,来编程的
  38. * director可以复杂控制构建的一个步骤,具体的每个步骤的逻辑封装在具体的builder类中
  39. * 如果我们此时要更换一整套的构建逻辑,可以再搞一个新的builder类就可以了
  40. * 但是我们的整个构建步骤是没有任何改变的
  41. *
  42. * 如果整个构建步骤变化了,但是对构建的逻辑是没有影响的
  43. */
  44. public static class Director {
  45. private Builder builder;
  46. public Director(Builder builder){
  47. this.builder = builder;
  48. }
  49. public Product build(String field1, String field2, String field3){
  50. builder.field1(field1);
  51. builder.field2(field2);
  52. builder.field3(field3);
  53. return builder.create();
  54. }
  55. }
  56. public static class Product {
  57. private String field1;
  58. private String field2;
  59. private String field3;
  60. public String getField1() {
  61. return field1;
  62. }
  63. public void setField1(String field1) {
  64. this.field1 = field1;
  65. }
  66. public String getField2() {
  67. return field2;
  68. }
  69. public void setField2(String field2) {
  70. this.field2 = field2;
  71. }
  72. public String getField3() {
  73. return field3;
  74. }
  75. public void setField3(String field3) {
  76. this.field3 = field3;
  77. }
  78. @Override
  79. public String toString() {
  80. return "Product [field1=" + field1 + ", field2=" + field2 + ", field3=" + field3 + "]";
  81. }
  82. }
  83. }

目前最常用的构造器实现方式

image.png

package com.example.designpattern.builder;

public class OptimizedBuilderPatternDemo {
    public static void main(String[] args) {
        Product product = new ConcreteBuilder()
                .field1("值1")
                .field2("值2")
                .field3("值3")
                .create();
        System.out.println(product);
    }

    public interface Builder{
        Builder field1(String value);
        Builder field2(String value);
        Builder field3(String value);
        Product create();
    }

    public static class ConcreteBuilder implements Builder{
        private Product product = new Product();

        public Builder field1(String value) {
            System.out.println("在设置field1之前进行复杂的校验逻辑");
            product.setField1(value);
            return this;
        }

        public Builder field2(String value) {
            System.out.println("在设置field2之前进行复杂的数据格式转化逻辑");
            product.setField2(value);
            return this;
        }

        public Builder field3(String value) {
            System.out.println("在设置field3之前进行复杂的数据处理逻辑,跟其他对象的数据进行关联");
            product.setField3(value);
            return this;
        }

        public Product create() {
            return product;
        }
    }

    public static class Product {

        private String field1;
        private String field2;
        private String field3;

        public String getField1() {
            return field1;
        }
        public void setField1(String field1) {
            this.field1 = field1;
        }
        public String getField2() {
            return field2;
        }
        public void setField2(String field2) {
            this.field2 = field2;
        }
        public String getField3() {
            return field3;
        }
        public void setField3(String field3) {
            this.field3 = field3;
        }
        @Override
        public String toString() {
            return "Product [field1=" + field1 + ", field2=" + field2 + ", field3=" + field3 + "]";
        }
    }
}