设计模式之建造者模式

builder desigin pattern

建造者模式的概念、建造者模式的结构、建造者模式的优缺点、建造者模式的使用场景、建造者模式的实现示例、建造者模式的源码分析


1、建造者模式的概念

  将一个复杂对象的构建和表示分离,使得同样的创建过程可以得到不同的表示。其主要特点是将产品本身和产品创建过程解耦,且分解产品创建过程,使创建过程更加清晰,同时也方便控制产品的创建过程步骤。

2、建造者模式的结构

  • 产品:包含多个简单部分的复杂对象,由具体建造者负责创建各个简单部分。
  • 抽象建造者:定义了创建各个简单部分和返回复杂产品对象的抽象方法。
  • 具体建造者:实现抽象建造者,实现产品简单部分的具体创建。
  • 指挥者:调用建造者创建产品简单部分的方法来创建产品简单部分,然后调用建造者返回复杂产品对象的方法生成最终结果。在指挥者中不设计具体产品信息。

builder-class

3、建造者模式的优缺点

  • 优点:
    • 产品本身和创建过程解耦,使得相同的创建过程可以创建出不同的产品对象。
    • 每一个具体建造者都相对独立,与其它具体建造者无关,即若有新的具体建造者加入时不必修改原有的代码,满足开闭原则。
    • 更加精细的控制产品的创建过程。将复杂对象的创建分解成多个简单创建的步骤,使得创建过程更加清晰,同时也方便通过程序来控制产品的创建过程。
  • 缺点:
    • 使用范围一定程度受限。建造者模式所创建的产品一般具有较多共同点,如果产品之间差异较大则不适用。
    • 如果产品的内部变化复杂,则可能需要定义多个具体建造者来实现这种变化,这将会导致代码臃肿,降低代码可读性。

4、建造者模式的使用场景

  • 创建的对象较复杂,由多个组件构成,且各组件面临着复杂的变化,但组件间的构建顺序是稳定的。
  • 创建复杂对象的算法独立于该对象的组成部分以及它们的装配方式,即产品的构建过程和最终表示是独立的。

5、建造者模式的实现示例

复杂产品:

public class Product {

    private String partA;   // 产品的部分 A

    private String partB;   // 产品的部分 B

    private String partC;   // 产品的部分 C

    public String getPartA() {
        return partA;
    }

    public void setPartA(String partA) {
        this.partA = partA;
    }

    public String getPartB() {
        return partB;
    }

    public void setPartB(String partB) {
        this.partB = partB;
    }

    public String getPartC() {
        return partC;
    }

    public void setPartC(String partC) {
        this.partC = partC;
    }

    @Override
    public String toString() {
        return "Product{" +
                "partA='" + partA + '\'' +
                ", partB='" + partB + '\'' +
                ", partC='" + partC + '\'' +
                '}';
    }
}

抽象构建者:

public abstract class Builder {

    protected Product product = new Product();   // 产品实例

    public abstract void buildPartA();   // 构建产品的部分 A

    public abstract void buildPartB();   // 构建产品的部分 B

    public abstract void buildPartC();   // 构建产品的部分 C

    /**
     * 返回产品实例
     * @return
     */
    public Product builder() {
        return product;
    }
}

具体构建者一:

public class OneBuilder extends Builder {

    @Override
    public void buildPartA() {
        product.setPartA("一的部分 a");
    }

    @Override
    public void buildPartB() {
        product.setPartB("一的部分 b");
    }

    @Override
    public void buildPartC() {
        product.setPartC("一的部分 c");
    }
}

具体构建者二:

public class TwoBuilder extends Builder {

    @Override
    public void buildPartA() {
        product.setPartA("二的部分 a");
    }

    @Override
    public void buildPartB() {
        product.setPartB("二的部分 b");
    }

    @Override
    public void buildPartC() {
        product.setPartC("二的部分 c");
    }
}

指挥者:

public class Director {

    private Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }

    public void setBuilder(Builder builder) {
        this.builder = builder;
    }

    /**
     * 按照产品的构建步骤构建产品
     * @return
     */
    public Product buildProduct() {
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
        return builder.builder();
    }
}

测试:

public class BuilderTest {

    public static void main(String[] args) {
        Builder oneBuilder = new OneBuilder();
        Builder twoBuilder = new TwoBuilder();

        Director director = new Director(oneBuilder);
        Product oneProduct = director.buildProduct();

        director.setBuilder(twoBuilder);
        Product twoProduct = director.buildProduct();

        System.out.println(oneProduct);
        System.out.println(twoProduct);
    }
}

测试结果:

Product{partA='一的部分 a', partB='一的部分 b', partC='一的部分 c'}
Product{partA='二的部分 a', partB='二的部分 b', partC='二的部分 c'}

6、建造者模式的源码分析

  建造者模式出上述用途外,其在在 jdk、spring 等源码中以及日常开发中最常用的另外一种方式则是:当一个构造器需要传入很多参数时,其代码可读性会较差,且很容易引入错误,此时就可以利用建造者模式。

public class Three {

    private String partA;

    private String partB;

    private String partC;

    public Three(Builder builder) {
        this.partA = builder.partA;
        this.partB = builder.partB;
        this.partC = builder.partC;
    }

    public static class Builder {

        private String partA;

        private String partB;

        private String partC;

        public Builder() {}

        public Builder partA(String partA) {
            this.partA = partA;
            return this;
        }

        public Builder partB(String partB) {
            this.partB = partB;
            return this;
        }

        public Builder partC(String partC) {
            this.partC = partC;
            return this;
        }

        public Three build() {
            return new Three(this);
        }
    }
}
Three three = new Three.Builder()
                .partA("a")
                .partB("b")
                .partC("v")
                .build();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值