美文网首页
建造者模式

建造者模式

作者: jianshujoker | 来源:发表于2020-04-09 08:46 被阅读0次

    定义

    将一个复杂对象的构建与表示分离,同样的构建过程创建不同的表示

    • 构建:有些情况,一个对象的性质必须依赖于某个顺序赋值才有意义,这使得构建对象具有复杂的逻辑,因此,这个构建过程可以被外部化到一个叫建造者的对象里,建造者将构建好的产品返回给客户端
    • 表示:一个产品有不同的组成部分,不同的产品有不同的组成部分,建造者模式使得客户端不用知道所生产的产品有哪些部分,有什么差异,是怎么构建出来的。就像房子,买房者得到的是修建好的房子,而不用关心房子是怎么建造好的

    应用场景

    • 产品较复杂,需要赋值的属性不一时
    • 多个部件或零件都可以装配到一个对象上,但产生的结果不同
    • 产品类中的调用顺序不同产生不同的结果

    常用写法

    标准写法

    • 产品
    /**
     * 产品
     */
    @Data
    public class Product {
        /**
         * 需要建造的A部分
         */
        private String partA;
    
        /**
         * 需要建造的B部分
         */
        private String partB;
    }
    
    • 建造者接口
    /**
     * 建造者接口,定义行为
     */
    public interface IBuilder {
        /**
         * 建造A部分
         */
        void buildPartA();
    
        /**
         * 建造B部分
         */
        void buildPartB();
    
        /**
         * 给出建造好的产品
         */
        Product build();
    }
    
    • 实际的建造者
    /**
     * 实际的建造者,当只有一个建造者的时候,通常会省去IBuilder的定义
     */
    public class ConcreteBuilder implements IBuilder {
        private Product product = new Product();
    
        @Override
        public void buildPartA() {
            product.setPartA("A");
        }
    
        @Override
        public void buildPartB() {
            product.setPartB("B");
        }
    
        @Override
        public Product build() {
            return product;
        }
    }
    
    • 指挥者、调用者
    /**
     * 指挥者,负责产品部分完整建造或按顺序创建,就像建造房子时,施工队不和客户交流,而是有个管理者
     * 指挥先建地基,后建房子,然后装修,最后交出建造好的房子给客户一样
     */
    public class Director {
        public static void main(String[] args) {
            IBuilder builder = new ConcreteBuilder();
            builder.buildPartA();
            builder.buildPartB();
            Product product = builder.build();
        }
    }
    
    • 类图


      建造者模式标准写法.png

    lombock builder

    • 原始代码
    import lombok.Builder;
    import lombok.Data;
    /**
     * 产品
     */
    @Builder
    @Data
    public class Product {
        /**
         * 需要建造的A部分
         */
        private String partA;
    
        /**
         * 需要建造的B部分
         */
        private String partB;
    }
    
    • lombock 实际构建的builder
    public class Product {
        private String partA;
        private String partB;
    
        Product(final String partA, final String partB) {
            this.partA = partA;
            this.partB = partB;
        }
    
        public static Product.ProductBuilder builder() {
            return new Product.ProductBuilder();
        }
    
        public String getPartA() {
            return this.partA;
        }
    
        public String getPartB() {
            return this.partB;
        }
    
        public void setPartA(final String partA) {
            this.partA = partA;
        }
    
        public void setPartB(final String partB) {
            this.partB = partB;
        }
    
        public boolean equals(final Object o) {
            if (o == this) {
                return true;
            } else if (!(o instanceof Product)) {
                return false;
            } else {
                Product other = (Product)o;
                if (!other.canEqual(this)) {
                    return false;
                } else {
                    Object this$partA = this.getPartA();
                    Object other$partA = other.getPartA();
                    if (this$partA == null) {
                        if (other$partA != null) {
                            return false;
                        }
                    } else if (!this$partA.equals(other$partA)) {
                        return false;
                    }
    
                    Object this$partB = this.getPartB();
                    Object other$partB = other.getPartB();
                    if (this$partB == null) {
                        if (other$partB != null) {
                            return false;
                        }
                    } else if (!this$partB.equals(other$partB)) {
                        return false;
                    }
    
                    return true;
                }
            }
        }
    
        protected boolean canEqual(final Object other) {
            return other instanceof Product;
        }
    
        public int hashCode() {
            int PRIME = true;
            int result = 1;
            Object $partA = this.getPartA();
            int result = result * 59 + ($partA == null ? 43 : $partA.hashCode());
            Object $partB = this.getPartB();
            result = result * 59 + ($partB == null ? 43 : $partB.hashCode());
            return result;
        }
    
        public String toString() {
            return "Product(partA=" + this.getPartA() + ", partB=" + this.getPartB() + ")";
        }
    
        public static class ProductBuilder {
            private String partA;
            private String partB;
    
            ProductBuilder() {
            }
    
            public Product.ProductBuilder partA(final String partA) {
                this.partA = partA;
                return this;
            }
    
            public Product.ProductBuilder partB(final String partB) {
                this.partB = partB;
                return this;
            }
    
            public Product build() {
                return new Product(this.partA, this.partB);
            }
    
            public String toString() {
                return "Product.ProductBuilder(partA=" + this.partA + ", partB=" + this.partB + ")";
            }
        }
    }
    
    • 使用lombok的builder的好处
      • 方便:只需要加一个@Builder,隐去了director和Ibuilder,帮助创建实际的建造者ProductBuilder,而不需要自己写
      • 链式构建对象,不用一个一个去set

    优缺点

    优点

    • 封装性好,创建和使用分离
    • 扩展性好,建造类之间独立

    缺点

    • 产生多余的对象
    • 产品改变时,建造者也需要一起跟着变

    相关文章

      网友评论

          本文标题:建造者模式

          本文链接:https://www.haomeiwen.com/subject/jshqmhtx.html