设计模式 | 建造者模式

159 阅读4分钟

建造者模式概述

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

建造者模式是一种创建型设计模式。

建造者模式又可以称为生成器模式。

建造者模式结构图

image-20220719143103822

建造者模式包含如下4种角色:

(1)产品 (Prod­uct):要创建的产品类对象。

(2)建造者(Builder):建造者的抽象类,规范产品对象的各个组成部分的创建,一般由子类实现具体的创建过程。

(3)建造者实现 (Con­crete Builder):根据不同的业务逻辑,具体实现产品对象的各个组成部分的创建。

(4)指导者(Director):调用具体的创建者,来创建对象的各个组成部分。

建造者模式的适用场景

(1)需要生产的产品对象有复杂的内部结构,这些产品对象具备共性。

(2)隔离复杂产品的创建和使用,并使用相同的创建过程可以创建不同的产品。

(3)适合于一个具有较多的组件的产品的创建过程。

建造者模式的优缺点

优点:

(1)产品的构造与表示分离,实现了解耦。使用建造者模式可以使客户端不必知道产品内部组成的细节。

(2)将复杂方法的创建步骤分解在不同的方法中,使得创建过程更加清晰。

(3)具体的建造者间是相互独立的,这有利于系统的扩展。增加新的具体建造者无需修改原有类库的代码,符合“开闭原则”。

缺点:

(1)建造者模式所创建的产品一般有较多的共同点,其组成部分相似,如果产品间差异较大,则不适合使用建造者模式。即建造者模式的使用范围有一定的限制。

(2)如果产品的内部变化复杂,可能需要定义很多具体的建造者来实现这种变化,导致系统变得庞大。

代码实现

为了简化其数据模型,我们将组成建筑物的模块归纳为3个组件,分别是地基、墙体、屋顶,将它们组装起来就能形成一座建筑物。

Building.java —— 建筑物

import java.util.ArrayList;
import java.util.List;

/**
 * 建筑物
 */
public class Building {
    // 建筑物组件
    private List<String> components = new ArrayList<>();
    // 地基
    public void setBasement(String basement) {
        this.components.add(basement);
    }
    // 墙体
    public void setWall(String wall) {
        this.components.add(wall);
    }
    // 屋顶
    public void setRoof(String roof) {
        this.components.add(roof);
    }
    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();
        for (int i = this.components.size() - 1; i>= 0; i--) {
            sb.append(this.components.get(i));
        }
        return sb.toString();
    }
}

Builder.java —— 施工方

/**
 * 施工方
 */
public interface Builder {
    // 建造地基
    void buildBasement();
    // 建造墙体
    void buildWall();
    // 建造屋顶
    void buildRoof();
    // 获取建筑物
    Building getBuilding();
}

ApartmentBuilder.java —— 公寓施工方

/**
 * 公寓施工方
 */
public class ApartmentBuilder implements Builder {
    private Building apartment;
    public ApartmentBuilder() {
        this.apartment = new Building();
    }
    @Override
    public void buildBasement() {
        System.out.println("深挖地基,修建地下车库,部署管道、线缆、风道。");
        apartment.setBasement("╚═════════╝\n");
    }
    @Override
    public void buildWall() {
        System.out.println("搭建多层建筑框架,建造电梯井,钢筋混凝土浇灌。");
        for(int i = 0; i < 8; i++) {
            apartment.setWall("║ □ □ □ □ ║\n");
        }
    }
    @Override
    public void buildRoof() {
        System.out.println("封顶,部署通风井,做防水层,保温层。");
        apartment.setRoof("╔═════════╗\n");
    }
    @Override
    public Building getBuilding() {
        return this.apartment;
    }
}

HouseBuilder.java —— 别墅施工方

/**
 * 别墅施工方
 */
public class HouseBuilder implements Builder {
    private Building house;
    public HouseBuilder() {
        this.house = new Building();
    }
    @Override
    public void buildBasement() {
        System.out.println("挖土方,部署管道、线缆,水泥加固,搭建围墙、花园。");
        this.house.setBasement("╬╬╬╬╬╬╬╬╬\n");
    }

    @Override
    public void buildWall() {
        System.out.println("搭建木质框架,石膏板封墙并粉饰内外墙。");
        this.house.setWall("|田|田|田|\n");
    }

    @Override
    public void buildRoof() {
        System.out.println("建造木质屋顶、阁楼,安装烟囱,做好防水。");
        this.house.setRoof("╱◥█████◣\n");
    }

    @Override
    public Building getBuilding() {
        return this.house;
    }
}

Director.java —— 工程总监

/**
 * 工程总监
 */
public class Director {
    private Builder builder;
    public Director(Builder builder) {
        this.builder = builder;
    }
    public void setBuilder(Builder builder) {
        this.builder = builder;
    }
    public void direct() {
        System.out.println("=====工程项目启动=====");
        // 第一步,打好地基
        builder.buildBasement();
        // 第二步,建造框架、墙体
        builder.buildWall();
        // 第三步,封顶
        builder.buildRoof();
        System.out.println("=====工程项目竣工=====");
        System.out.println(builder.getBuilding());
    }
}

Client.java —— 客户端

public class Client {
    public static void main(String[] args) {
        // 别墅施工方
        Director director = new Director(new HouseBuilder());
        director.direct();
        // 公寓施工方
        director.setBuilder(new ApartmentBuilder());
        director.direct();
    }
}

输出结果:

=====工程项目启动=====
挖土方,部署管道、线缆,水泥加固,搭建围墙、花园。
搭建木质框架,石膏板封墙并粉饰内外墙。
建造木质屋顶、阁楼,安装烟囱,做好防水。
=====工程项目竣工=====
╱◥█████◣
|田|田|田|
╬╬╬╬╬╬╬╬╬

=====工程项目启动=====
深挖地基,修建地下车库,部署管道、线缆、风道。
搭建多层建筑框架,建造电梯井,钢筋混凝土浇灌。
封顶,部署通风井,做防水层,保温层。
=====工程项目竣工=====
╔═════════╗
║ □ □ □ □ ║
║ □ □ □ □ ║
║ □ □ □ □ ║
║ □ □ □ □ ║
║ □ □ □ □ ║
║ □ □ □ □ ║
║ □ □ □ □ ║
║ □ □ □ □ ║
╚═════════╝