写点什么

设计模式之建造者模式

作者:游坦之
  • 2022-10-17
    山东
  • 本文字数:3623 字

    阅读完需:约 1 分钟

设计模式之建造者模式

1 定义

建造者模式(Builder Patten):将一个复杂对象的构建与他的表示分离,使得同样的构建过程可以创建不同的表示。


建造者模式用于一步一步创建一个复杂的对象,他允许用户只通过指定复杂对象的类型和内容进行构建,用户不需要知道内部的具体构建细节。建造者模式属于对象创建型模式,根据翻译的不同,建造者模式又可称为生成器模式。

2 结构与角色

建造者模式包含 4 个角色


  • Builder:抽象建造者。为创建一个 Product 对象的各个部件指定的抽象接口。

  • ConcreteBuilder:具体建造者。实现抽象建造者 Builder,构建和装配产品的各个部件。做具体建造工作,但却不为客户端所知。

  • Product:产品,被构建的复杂对象。具体建造者创建该产品的内部表示并定义它的装配过程。包含定义组成部件的类,包括将这些部件装配成最终的产品的接口。

  • Director:指挥者。构建一个使用抽象建造者 Builder 的对象。它与客户端打交道,将客户端创建产品的请求划分为对各个零件的建造请求,再将这些请求委派给 ConcreteBuilders。

3 例子

建造楼房的过程中,有专业人员绘制图纸,图纸中讲述干什么工人根据图纸去具体实现要干的事情包工头根据实际情况去处理图纸中方法的执行,调配工人以何种顺序完成图纸上的要求。虽然包工头和图纸对建造高楼很有帮助,但是高楼平地起,却是由工人们一砖一瓦的搭建起来。


以上的这个例子很形象的讲述建造者模式执行过程,其中图纸就对应 Builder(提供方法,要干什么),工人就对应 ConcreteBuilder(具体去干方法中规定的事情),包工头就对应 Director(以何种顺序干,调配工人),高楼就对应 Product。

3.1 代码

3.1.1 Builder 类

Builder 类只提供抽象的方法,类似于图纸,只是告诉你建造高楼你需要做什么。


// 抽象方法,要做什么:建设一个大楼需要做什么public abstract class Builder {    abstract void builderA();    abstract void builderB();    abstract void builderC();    abstract void builderD();    abstract Product getProduct();}
复制代码

3.1.2 Worker 类

工人是具体实现 Builder 提出的需求,比如水泥、钢筋等等。工人类直接产生产品(new


package demo01;
// 知道了要做什么,就得有人来具体实现public class Worker extends Builder{ private Product product;
public Worker() { product = new Product(); }
@Override void builderA() { product.setBuildA("打地基"); System.out.println("打地基"); }
@Override void builderB() { product.setBuildB("钢筋混凝土"); System.out.println("钢筋混凝土"); }
@Override void builderC() { product.setBuildC("盖房子"); System.out.println("盖房子"); }
@Override void builderD() { product.setBuildD("油漆、粉刷"); System.out.println("油漆、粉刷"); } Product getProduct() { return product; }}
复制代码

3.1.3 Product 类

当产品的本身的属性一一被满足的时候,产品才会产生。


public class Product {    private String buildA;    private String buildB;    private String buildC;    private String buildD;
public String getBuildA() { return buildA; }
public void setBuildA(String buildA) { this.buildA = buildA; }
public String getBuildB() { return buildB; }
public void setBuildB(String buildB) { this.buildB = buildB; }
public String getBuildC() { return buildC; }
public void setBuildC(String buildC) { this.buildC = buildC; }
public String getBuildD() { return buildD; }
public void setBuildD(String buildD) { this.buildD = buildD; }
@Override public String toString() { return "Product{" + "buildA='" + buildA + '\'' + ", buildB='" + buildB + '\'' + ", buildC='" + buildC + '\'' + ", buildD='" + buildD + '\'' + '}'; }}
复制代码

3.1.4 Director 类

包工头,安排工人怎么去做,比如今天下雨,不打水泥了,去抬钢筋,今天不下雨了,去打地基。


// 指挥的作用是,以什么样的顺序,完成产品的制作public class Director {    public Product getProduct(Builder builder){        builder.builderA();        builder.builderB();        builder.builderC();        builder.builderD();        return builder.getProduct();    }}
复制代码

3.1.5 Test 测试类

public class Test01 {    public static void main(String[] args) {        Director director = new Director();        Product product = director.getProduct(new Worker());        System.out.println(product.toString());    }}
复制代码



指挥者调整顺序可以得到不同的产品,或者不同的效果(虽然这个没体现出来)


4 不使用指挥者的例子

去餐厅吃饭,餐厅里一般有默认的套餐,或者自己(用户)点餐,点餐之后,服务员根据订单负责将食品端上来,然后你大快朵颐,享受美食带来的快感....


在这一场景里,就没有指挥者,指挥权到达了用户的手里。上面 3 中的场景,指挥权就不能到用户手里,你不能让人家掏钱还得让人家自己建(除非是老板)。

4.1 Builder 类

public abstract class Builder {    abstract Builder builderA(String msg);    abstract Builder builderB(String msg);    abstract Builder builderC(String msg);    abstract Builder builderD(String msg);    abstract Product getProduct();}
复制代码

4.2 Worker 类

public class Worker extends Builder {    private Product product;
public Worker() { product = new Product(); }

Builder builderA(String msg) { product.setBuildA(msg); return this; }
Builder builderB(String msg) { product.setBuildB(msg); return this; }
Builder builderC(String msg) { product.setBuildC(msg); return this; }
Builder builderD(String msg) { product.setBuildD(msg); return this; } Product getProduct() { return product; }}
复制代码

4.3 Product 类

public class Product {    private String buildA = "炸鸡";    private String buildB = "汉堡";    private String buildC = "可乐";    private String buildD = "大蒜";
public String getBuildA() { return buildA; }
public void setBuildA(String buildA) { this.buildA = buildA; }
public String getBuildB() { return buildB; }
public void setBuildB(String buildB) { this.buildB = buildB; }
public String getBuildC() { return buildC; }
public void setBuildC(String buildC) { this.buildC = buildC; }
public String getBuildD() { return buildD; }
public void setBuildD(String buildD) { this.buildD = buildD; }
@Override public String toString() { return "Product{" + "buildA='" + buildA + '\'' + ", buildB='" + buildB + '\'' + ", buildC='" + buildC + '\'' + ", buildD='" + buildD + '\'' + '}'; }}
复制代码

4.4 Test 类

public class Test {    public static void main(String[] args) {        Worker worker = new Worker();        System.out.println(worker.builderA("全家桶")                .getProduct());    }}
复制代码


上面的代码例子中:Worker 就相当于服务员,记录你点了什么菜,并生成账单(Product 里的信息),反馈给用户产品。


5 适用场景

  • 需要生成的产品对象有复杂的内部结构(通常包含多个成员属性)

  • 需要生成的产品对象的属性相互依赖(需要指定顺序)

  • 产品对象的创建过程独立于创建该对象的类

  • 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的类

6 优缺点

6.1 优点

  • 用户不需要知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。

  • 很方便的替换具体的建造者或者增加新的具体创建者

  • 符合开闭原则,可以更加精细的控制产品的创建过程

6.2 缺点

  • 适用范围收到限制,需要生成的产品对象具有较多共同点

  • 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化。

发布于: 刚刚阅读数: 3
用户头像

游坦之

关注

还未添加个人签名 2022-10-14 加入

还未添加个人简介

评论

发布
暂无评论
设计模式之建造者模式_设计模式_游坦之_InfoQ写作社区