设计模式之建造者模式

定义

Builder模式,即建造者模式,也被称作生成器模式,属于创建型设计模式的一种。它旨在将一个复杂对象的构建过程与其表示过程分离,使得同样的构建过程可以创建不同的表示。此模式的核心思想是将复杂对象的构建分解成一系列步骤,并将这些步骤封装在独立类中,即所谓的建造者类,以实现构建和表示的解耦。

建造者模式的核心在于“变与不变”的分离。在软件系统中,经常面临的情况是某些对象的组成部分(即不变的部分)是固定的,但这些部分的组合方式(即变化的部分)可能会频繁地变化。建造者模式通过将不变的部分封装在抽象建造者接口中,而将变化的部分留给具体建造者类来实现,从而实现了变与不变的分离。

在建造者模式中,通常涉及以下关键角色:

  • 产品(Product):这是最终构建出的复杂对象,它包含多个属性和一些核心方法。
  • 抽象建造者(Builder):定义创建产品各个部分的接口,规定了构建步骤的框架,不涉及具体实现。
  • 具体建造者(ConcreteBuilder):实现了抽象建造者的接口,负责具体构建产品的各个部分,每个具体建造者通常对应产品的特定变体或配置。
  • 指挥者(Director):负责管理整个构建过程,确保按照既定步骤和顺序完成产品的构建。

应用示例

以下是一个简化的Java代码示例,用于展示创建者模式在构建计算机对象时的应用:

// 产品:计算机,它包含了CPU、内存和硬盘等属性
public class Computer {
    private String cpu;
    private String memory;
    private String hardDisk;

    // 私有构造器,因为我们将通过具体建造者来创建Computer对象
    private Computer(Builder builder) {
        this.cpu = builder.cpu;
        this.memory = builder.memory;
        this.hardDisk = builder.hardDisk;
    }

    public static Builder builder() {
        return new Builder();
    }

    // 静态内部类:具体建造者
    public static class Builder {
        private String cpu;
        private String memory;
        private String hardDisk;

        // 链式调用的setter方法
        public Builder withCpu(String cpu) {
            this.cpu = cpu;
            return this; // 返回this以实现链式调用
        }

        public Builder withMemory(String memory) {
            this.memory = memory;
            return this;
        }

        public Builder withHardDisk(String hardDisk) {
            this.hardDisk = hardDisk;
            return this;
        }

        // 构建并返回产品
        public Computer build() {
            return new Computer(this);
        }
    }

    // 展示计算机信息的方法
    @Override
    public String toString() {
        return "Computer{" +
                "cpu='" + cpu + '\'' +
                ", memory='" + memory + '\'' +
                ", hardDisk='" + hardDisk + '\'' +
                '}';
    }

    // 主方法,用于演示如何使用建造者模式创建计算机对象
    public static void main(String[] args) {
        // 创建一个具体的建造者并设置属性值
        Computer computer = Computer.builder()
                .withCpu("Intel Core i9")
                .withMemory("16GB DDR4")
                .withHardDisk("1TB SSD")
				.build();

        // 打印计算机信息 输出:Computer{cpu='Intel Core i9', memory='16GB DDR4', hardDisk='1TB SSD'}
        System.out.println(computer);
    }
}

在上述示例中,我们关注了产品和具体建造者的实现,而没有引入抽象建造者和指挥者。这是因为,在构建过程较为简单或不需要多种构建方式的情形下,可以简化建造者模式,将指挥者的职责整合进具体建造者。这种简化有助于减少系统复杂性,但需注意,它可能会破坏单一职责原则并增加组件间的耦合度。

为了引入抽象建造者和指挥者,我们将对上述示例进行以下改造:

  1. 首先,我们定义一个产品计算机(Computer)。
public class Computer {
    private String cpu;
    private String memory;
    private String hardDisk;

    public void setCpu(String cpu) {
        this.cpu = cpu;
    }

    public void setMemory(String memory) {
        this.memory = memory;
    }

    public void setHardDisk(String hardDisk) {
        this.hardDisk = hardDisk;
    }

    @Override
    public String toString() {
        return "Computer{" +
                "cpu='" + cpu + '\'' +
                ", memory='" + memory + '\'' +
                ", hardDisk='" + hardDisk + '\'' +
                '}';
    }
}
  1. 接着,定义一个抽象建造者(Builder)和具体建造者(ConcreteBuilder)。
public interface Builder {
    Builder withCpu(String cpu);
    Builder withMemory(String memory);
    Builder withHardDisk(String hardDisk);
    Computer build();
}

public class ConcreteBuilder implements Builder {
   private Computer computer;

    public ConcreteBuilder() {
        this.computer = new Computer();
    }

    @Override
    public Builder withCpu(String cpu) {
        computer.setCpu(cpu);
        return this;
    }

    @Override
    public Builder withMemory(String memory) {
        computer.setMemory(memory);
        return this;
    }

    @Override
    public Builder withHardDisk(String hardDisk) {
        computer.setHardDisk(hardDisk);
        return this;
    }

    @Override
    public Computer build() {
        return computer;
    }
}
  1. 然后,定义一个指挥者(Director)。
public class Director {
    private final Builder builder;

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

    public void construct() {
        builder.withCpu("Intel Core i9")
                .withMemory("16GB DDR4")
                .withHardDisk("1TB SSD");
    }
}
  1. 最后,创建一个客户端类来演示如何使用。
public class Client {
    public static void main(String[] args) {
        Builder builder = new ConcreteBuilder();
        Director director = new Director(builder);
        director.construct();

        Computer computer = builder.build();
        // 打印计算机信息 输出:Computer{cpu='Intel Core i9', memory='16GB DDR4', hardDisk='1TB SSD'}
        System.out.println(computer);
    }
}

优缺点分析

优点:

  • 封装性好:建造者模式将复杂对象的构建过程封装在建造者类中,客户端只需要知道建造者接口,而不需要知道具体的构建细节,这降低了客户端与具体构建过程的耦合度。
  • 优秀的扩展性:由于建造者模式的构建过程与表示过程分离,因此可以通过定义不同的建造者类来创建不同的表示,这使得系统具有很好的扩展性。此外,具体建造者相互独立,方便扩展,符合开闭原则。
  • 便于控制细节风险:在建造者模式中,客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,这有助于降低系统的复杂性并减少出错的可能性。

缺点:

  • 对象的构建过程变得更加繁琐:相比直接使用构造器创建对象,使用建造者模式需要调用多个方法来设置对象的属性,这增加了构建对象的步骤和复杂度。如果一个类只有很少的属性,使用建造者模式可能会显得过于繁琐和复杂。
  • 一定的使用范围限制:建造者模式要求产品的组件基本相同,如果产品的差异性较大,建造者模式可能就不适用了。此外,如果产品内部变化复杂,建造者也需要同步修改,这会增加后期维护的成本。

总结

建造者模式是一种强大的创建型设计模式,它通过将复杂对象的构建过程分解为一系列步骤,并将这些步骤封装在单独的建造者类中,从而实现了变与不变的分离。这种模式不仅提高了代码的可读性和可维护性,还使得代码更加灵活和易于扩展。在实际开发中,我们应该根据具体需求来选择合适的设计模式,以提高代码质量、降低维护成本。

  • 25
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丿微风乍起

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值