前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式实战-建造者模式,做任何事情都需要步步为营

设计模式实战-建造者模式,做任何事情都需要步步为营

作者头像
架构师修炼
发布2020-07-17 12:18:15
5460
发布2020-07-17 12:18:15
举报
文章被收录于专栏:架构师修炼架构师修炼

1、定义

所谓万丈高楼平地起,但是我们建造(Build)高楼时,需要经历很多阶段,比如打地基、搭框架、浇筑水泥、封顶等,这些都是很难一气呵成的。所以一般我们是先建造组成高楼的各个部分,然后将其一个个地组装起来,好比搭积木一般,分阶段拼接后组装成一个完整的物体。还有个问题,就是同样的积木,同样的搭建过程,却能 Build 出不同的物体,这就叫做建造者模式。

将一个复杂的对象的构建与它的表示相分离,使得同样的构建过程可以创建出不同的表示。建造者模式(Builder Pattern)也叫做生成器模式。

2、组成角色

建造者模式通常有以下几部分角色组成:

  • 建造者(Builder):Builder 角色负责定义用来生成实例的接口(API);
  • 具体的建造者(ConcreateBuilder):ConcreateBuilder 角色是负责实现 Builder 角色定义的接口的实现类。针对不同的商业逻辑,具体化复杂对象的各部分的创建。在建造完成之后提供产品的实例;
  • 监工(Director):Director 角色负责使用 Builder 角色的接口 API 来生成实例。内部不涉及具体产品信息,只负责保证对象各部分完整创建或按照某种顺序进行创建。即 Director 是负责指挥如何 build 的,只负责调度,具体实施交给具体的建造者;
  • 产品(Product):即要创建的复杂对象;
  • 使用者(Client):实际使用 Builder 模式的角色,即下面的测试类。

3、建造者模式 UML 类图

我们还是以最开始讲的建造大楼为例,其 UML 类图大致如下:

建造者模式的代码实现如下,首先是产品类(Product):

代码语言:javascript
复制
public class Product {
    private String ground;
    private String cement;
    private String roof;

    public Product() {
    }

    public String getGround() {
        return ground;
    }

    public void setGround(String ground) {
        this.ground = ground;
    }

    public String getCement() {
        return cement;
    }

    public void setCement(String cement) {
        this.cement = cement;
    }

    public String getRoof() {
        return roof;
    }

    public void setRoof(String roof) {
        this.roof = roof;
    }
}

然后是抽象的建造者角色:

代码语言:javascript
复制
public interface Builder {

    // 一般来说,有多少零配件,就有多少建造方法
    void buildGround();
    void buildCement();
    void buildRoof();

    // 返回产品类
    Product buildProduct();

}

建造者的实现类:

代码语言:javascript
复制
public class ConcreteBuilder implements Builder{

    private final Product product = new Product();

    @Override
    public void buildGround() {
        System.out.println("build地基");
        product.setGround("build地基");
    }

    @Override
    public void buildCement() {
        System.out.println("build水泥");
        product.setGround("build水泥");
    }

    @Override
    public void buildRoof() {
        System.out.println("build楼顶");
        product.setGround("build楼顶");
    }

    @Override
    public Product buildProduct() {
        System.out.println("建造完毕!");
        return product;
    }
}

然后是我们的监工,负责指挥 builder 如何建造即如何调度:

代码语言:javascript
复制
public class Director {
    private Builder builder;

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

    public Product construct() {
        // 构建顺序:建造水泥->地基->楼顶
        builder.buildCement();
        builder.buildGround();
        builder.buildRoof();

        return builder.buildProduct();
    }
}

最后,是 Client 角色,即具体的使用者,这里的话就是测试的 Main 类:

代码语言:javascript
复制
public class Main {

    public static void main(String[] args) {
        Builder builder = new ConcreteBuilder();
        Director director = new Director(builder);
        director.construct();

    }
}

输出结果如下:

代码语言:javascript
复制
build水泥
build地基
build楼顶
建造完毕!

4、优缺点

  • 封装性:客户端不必知道产品内部组合细节,只需关心我们要生成某个对象,具体对象产生细节不必知晓。Main 类并不知道 Builder 类,它只是调用了 Director 类的 construct 方法完成对象的获取;
  • 建造者独立,易于拓展:上面我们只列举了 ConcreteBuilder 建造者类,如果需要其它建造者新建类即可。建造者之间彼此独立,系统拓展性好,符合开闭原则;
  • 便于控制细节风险:由于具体建造者是独立的,因此可以对具体建造过程逐步细化,不会对其它模块产生影响。

5、应用场景

建造者模式的典型应用场景如下:

  • 产品类非常复杂,不同的调度产生不同的结果时,使用建造者模式比较适合;
  • 相同的组件或配件都可以装配到一个对象,但是产生的结果又不相同,可以使用建造者模式。

6、建造者模式 VS 工厂方法模式

建造者模式关注的是零件类型和装配顺序(工艺)同为创建型模式,注重点不同。另外工厂模式只有一个建造方法,而建造者模式有多个建造零部件的方法并且强调建造顺序,而工厂模式没有顺序的概念。

7、总结

将复杂物体的构建与表现相分离,这就是建造者模式,很像生活中搭积木这种,一个个按需要按方式进行拼凑,建造者模式适应于产品类比较复杂调度方式不一的场景。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构师修炼 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、定义
  • 2、组成角色
  • 3、建造者模式 UML 类图
  • 4、优缺点
  • 5、应用场景
  • 6、建造者模式 VS 工厂方法模式
  • 7、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档