标签 设计模式
 标签 建造者模式
 分类 Java
 分类 开发工具

死磕设计模式—建造者模式

前言(八问知识体系)

死磕设计模式-建造者模式

1.1.简介

  • 什么是建造模式?
    • 1.将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
    • 2.建造者模式是一步一步创建一个复杂的对象,建造者模式注重的是一步一步的创建复杂对象。这个和工厂模式存在区别
  • 建造模式的优缺点?
    • 优点
      • 1.将产品本身和其创建过程解耦,用户不需要知道内部组成的细节
      • 2.具体的建造者完全独立,使用不同的具体建造者生产不同的对象
      • 3.增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”
    • 缺点
      • 1.建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式
      • 2.如果产品内部变化很复杂,则需要大量的具体建造者,会导致系统更加庞大

1.2.类图

image-20191027200125458

1.3.代码示例

抽象的产品建造流程

public interface IBuilder {

    /**
     * buildPart1
     *
     * @description 建造产品的第一部分
     * @author luokangyuan
     * @date 2019/10/27 17:15
     * @version 1.0.0
     */
    void buildPart1();

    /**
     * buildPart2
     *
     * @description 建造产品的第二部分
     * @author luokangyuan
     * @date 2019/10/27 17:15
     * @version 1.0.0
     */
    void buildPart2();

    /**
     * buildPart3
     *
     * @description 建造产品的第三部分
     * @author luokangyuan
     * @date 2019/10/27 17:15
     * @version 1.0.0
     */
    void buildPart3();

    /**
     * build
     *
     * @description 得到产品
     * @return 产品
     * @author luokangyuan
     * @date 2019/10/27 17:16
     * @version 1.0.0
     */
    Product build();

具体的建造者

public class TruckConcreateBuilder implements IBuilder{

    private Product product = new Product();
    @Override
    public void buildPart1() {
        product.setPart1("货车轮胎完成");
    }

    @Override
    public void buildPart2() {
        product.setPart2("货车发动机完成");
    }

    @Override
    public void buildPart3() {
        product.setPart3("货车车架完成");
    }

    @Override
    public Product build() {
        return product;
    }
}
public class ConcreteBuilder implements IBuilder {
    private Product product = new Product();

    @Override
    public void buildPart1() {
        product.setPart1("轮胎完成");
    }

    @Override
    public void buildPart2() {
        product.setPart2("发动机完成");
    }

    @Override
    public void buildPart3() {
        product.setPart3("车架完成");
    }

    @Override
    public Product build() {
        return product;
    }
}

指挥者

@AllArgsConstructor
@Data
public class Conductor {

    private IBuilder builder;

    /**
     * construct
     *
     * @description 指挥者负责产品的创建流程
     * @return 产品
     * @author luokangyuan
     * @date 2019/10/27 19:13
     * @version 1.0.0
     */
    public Product construct() {
        builder.buildPart1();
        builder.buildPart2();
        builder.buildPart3();
        return builder.build();
    }
}

产品

@Data
public class Product {

    /* 组成产品的第一部分*/
    private String part1;

    /* 组成产品的第一部分*/
    private String part2;

    /* 组成产品的第一部分*/
    private String part3;
}

客户端调用

public static void main(String[] args) {
    IBuilder builder = new ConcreteBuilder();
    Conductor conductor = new Conductor(builder);
    Product product = conductor.construct();
    log.info("产品信息:{},{},{}", product.getPart1(), product.getPart2(),product.getPart3());
    conductor.setBuilder(new TruckConcreateBuilder());
    Product truck = conductor.construct();
    log.info("产品信息:{},{},{}", truck.getPart1(), truck.getPart2(), truck.getPart3());
}

实例详细类图

image-20191027191710468

1.4.总结和应用场景

  • 需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
  • 需要生成的产品对象的属性相互依赖,需要指定其生成顺序
  • 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品
  • 典型的lombok中的@Builder注解
  • 游戏人物的角色可以使用建造者模式,都有服装,技能,装备等共同属性
  • JDK中的StringBuilder使用了建造者模式
    • 1.Appendable接口定义了append抽象方法,就是一个抽象的建造者
    • 2.AbstractStringBuilder实现了Appendable,就是一个具体的建造者,但是不能实例化
    • 3.StringBuilder继承了AbstractStringBuilder,相当于一个具体建造者角色,同时还是一个指挥者角色
目录