23种设计模式之建设者设计模式

发布于:2024-11-27 ⋅ 阅读:(56) ⋅ 点赞:(0)

1. 简介

建造者模式(Builder Pattern)是一种创建型设计模式。它将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。简单来说,就是把对象的创建和对象的组装分开,这样可以更灵活地创建对象。
当我们需要创建一个复杂对象时,这个对象可能有很多属性,而且这些属性的设置顺序和组合方式可能有多种情况。如果直接在一个构造函数或者工厂方法中设置所有属性,代码会变得很复杂且难以维护。建造者模式通过将复杂对象的构建过程分解为多个步骤,由一个指挥者(Director)来控制这些步骤的执行顺序,而具体的构建步骤则由建造者(Builder)来实现。

结构组成:

  • 产品Product
    这是我们最终要创建的复杂对象。例如,在建造房屋的场景中,房屋就是产品。它可能包含多个部件,如房间、门窗、屋顶等。产品类通常有多个属性来表示其各个组成部分。
  • 抽象建造者Builder
    它定义了创建产品各个部件的抽象方法。这些方法规定了如何构建产品的各个部分。例如,抽象的房屋建造者可能有创建房间、创建门窗、安装屋顶等抽象方法
  • 具体建造者Concrete Builder
    它实现了抽象建造者的抽象方法,具体定义了如何构建产品的各个部分。不同的具体建造者可以按照不同的方式构建产品。比如,有一个豪华房屋建造者和一个普通房屋建造者,它们对房间数量、门窗质量、屋顶材料等的构建方式可能不同。
  • 指挥者Director
    指挥者负责控制建造过程,它知道如何正确地调用建造者的方法来构建产品。它通过调用建造者的方法来规定构建产品的步骤和顺序。例如,指挥者可以规定先建造房间,再安装门窗,最后安装屋顶。

2. 代码

在这里插入图片描述

2.1 Car

package yxz.builder;

public class Car {
    private String basePlate;

    private String frame;

    private String door;

    @Override
    public String toString() {
        return "Car{" +
                "basePlate='" + basePlate + '\'' +
                ", frame='" + frame + '\'' +
                ", door='" + door + '\'' +
                '}';
    }

    public String getBasePlate() {
        return basePlate;
    }

    public void setBasePlate(String basePlate) {
        this.basePlate = basePlate;
    }

    public String getFrame() {
        return frame;
    }

    public void setFrame(String frame) {
        this.frame = frame;
    }

    public String getDoor() {
        return door;
    }

    public void setDoor(String door) {
        this.door = door;
    }
}

2.2 Builder

package yxz.builder;

public abstract class Builder {
    public abstract void buildBasePlate(String basePlste);
    public abstract void buildFrame(String frame);
    public abstract void buildDoor(String door);

    public abstract Car makeCar();
}

2.3 CarBuilder

package yxz.builder;

public class CarBuilder extends Builder{
    private Car car = new Car();

    @Override
    public void buildBasePlate(String basePlste) {
        car.setBasePlate(basePlste);
    }

    @Override
    public void buildFrame(String frame) {
        car.setFrame(frame);
    }

    @Override
    public void buildDoor(String door) {
        car.setDoor(door);
    }

    @Override
    public Car makeCar() {
        return car;
    }
}

2.4 Engineer

package yxz.builder;

public class Engineer {
    private CarBuilder carBuilder;

    public void setCarBuilder(CarBuilder carBuilder) {
        this.carBuilder = carBuilder;
    }

    public Car makeCar(String basePlate, String door, String frame){
        carBuilder.buildBasePlate(basePlate);
        carBuilder.buildDoor(door);
        carBuilder.buildFrame(frame);
        return carBuilder.makeCar();
    }
}

2.5 Test

package yxz.builder;

public class Test {
    public static void main(String[] args) {
        CarBuilder carBuilder = new CarBuilder();
        // 创建工程师
        Engineer engineer = new Engineer();
        engineer.setCarBuilder(carBuilder);
        Car car = engineer.makeCar("制作车底盘","制作车门","制作车架");
        System.out.println(car);
    }
}

运行结果:

Car{basePlate='制作车底盘', frame='制作车架', door='制作车门'}

3. 总结

使用场景:

  • 复杂对象的创建
    当要创建的对象具有复杂的内部结构,并且其属性之间存在一定的依赖关系或者构建顺序要求时,适合使用建造者模式。例如,在创建一个汽车对象时,汽车有车身、发动机、轮胎等多个部件,而且这些部件的安装顺序很重要,并且不同类型的汽车(如轿车、SUV)在部件的具体构造上有所不同,就可以使用建造者模式。
  • 对象构建过程的复用
    如果有多个类似的对象需要创建,它们的构建过程大部分相同,只有部分细节不同,那么可以通过建造者模式复用构建过程。比如,在游戏开发中,要创建多种不同类型的怪物,怪物都有身体、武器、技能等部分,构建过程类似,但具体的身体形态、武器类型、技能效果等有所不同。可以定义一个怪物建造者,通过不同的具体建造者来创建不同的怪物,而构建过程(如先创建身体,再添加武器,最后赋予技能)可以在指挥者中复用。

优缺点:

  • 优点
    • 可扩展性强:可以很容易地通过增加新的具体建造者来创建新类型的产品。例如,如果要创建一种新型的房屋,只需要增加一个新的房屋建造者类,实现相应的构建方法即可。
    • 构建过程的复用:指挥者可以复用构建过程,使得相同的构建步骤可以用于创建不同的产品。这在需要批量创建相似对象时非常高效。
    • 封装性好:产品的构建过程封装在建造者和指挥者中,对于客户端代码来说,只需要关心最终产品的获取,不需要了解复杂的构建过程。
  • 缺点
    • 代码复杂度增加:由于引入了多个类(抽象建造者、具体建造者、指挥者等),会导致代码结构相对复杂,对于简单的对象创建场景可能会显得有些 “大材小用”。
    • 需要额外的代码维护成本:增加的类和它们之间的关系需要更多的代码来维护,特别是当产品的结构或者构建过程发生变化时,可能需要修改多个类的代码。

网站公告

今日签到

点亮在社区的每一天
去签到