【设计模式】【创建型模式】建造者模式(Builder)
👋hi,我不是一名外包公司的员工,也不会偷吃茶水间的零食,我的梦想是能写高端CRUD
🔥 2025本人正在沉淀中… 博客更新速度++
👍 欢迎点赞、收藏、关注,跟上我的更新节奏
🎵 当你的天空突然下了大雨,那是我在为你炸乌云
文章目录
- 一、入门
 
- 什么是建造者模式?
 - 为什么要建造者模式?
 - 如何实现建造者模式?
 
- 传统建造者
 - 链式建造者
 - 二、建造者模式在框架源码中的运用
 
- Java中的StringBuilder和StringBuffer
 - Spring Framework中的BeanDefinitionBuilder
 - 三、总结
 
- 建造者模式的优点
 - 建造者模式的缺点
 - 建造者模式的适用场景
 
一、入门
什么是建造者模式?
建造者模式(Builder Pattern)是一种创建型设计模式,用于逐步构建复杂对象。
 它通过将对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。
为什么要建造者模式?
假设我们要组装电脑,需要cpu、内存、硬盘、gpu、电源…
 没有使用建造者模式,我们会这样写:
public class Computer {
    private String cpu;
    private String memory;
    private String hardDisk;
    private String gpu;
    private String powerSupply;
    public Computer(String cpu, String memory, String hardDisk, String gpu, String powerSupply) {
        this.cpu = cpu;
        this.memory = memory;
        this.hardDisk = hardDisk;
        this.gpu = gpu;
        this.powerSupply = powerSupply;
    }
}
 
存在问题:
- 构造方法参数过多(Telescoping Constructor Problem):调用这样的构造方法时,代码会变得非常冗长且难以理解:
 
Computer computer = new Computer("Intel i7", "16GB", "1TB SSD", "NVIDIA RTX 3080", "750W");
 
- 对象的不一致性:在某些情况下,对象可能需要在不同的步骤中逐步构建。如果没有建造者模式,对象可能会在未完全初始化的情况下被使用,导致不一致的状态。
 - 代码的可读性可维护性变差:当对象的构建过程复杂时,直接在客户端代码中编写构建逻辑会导致代码重复和难以维护。
 
Computer computer = new Computer();
computer.setCpu("Intel i7");
computer.setMemory("16GB");
computer.setHardDisk("1TB SSD");
computer.setGpu("NVIDIA RTX 3080");
computer.setPowerSupply("750W");
 
- 缺乏灵活性:如果对象的构建过程需要支持多种不同的配置或表示形式,直接在客户端代码中编写构建逻辑会导致代码的灵活性降低。例如,如果需要构建不同类型的计算机(如游戏计算机、办公计算机等),每种类型的构建逻辑可能会有所不同,导致代码重复和难以扩展。
 
如何实现建造者模式?
传统建造者
主要角色
- Product(产品类):最终要构建的复杂对象。
 - Builder(抽象建造者):定义构建步骤的接口。
 - ConcreteBuilder(具体建造者):实现
Builder接口,提供具体的构建步骤。 - Director(指挥者):负责调用
Builder的步骤,控制构建过程。 
【案例】组装电脑 - 改
 
 Product(产品类):Computer类,最终要构建的复杂对象。
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 + "]";
    }
}
 
Builder(抽象建造者):ComputerBuilder接口,定义构建步骤的接口。
interface ComputerBuilder {
    void buildCpu();
    void buildMemory();
    void buildHardDisk();
    Computer getComputer();
}
 
ConcreteBuilder(具体建造者):GamingComputerBuilder类,实现Builder接口,提供具体的构建步骤。
class GamingComputerBuilder implements ComputerBuilder {
    private Computer computer;
    public GamingComputerBuilder() {
        this.computer = new Computer();
    }
    @Override
    public void buildCpu() {
        computer.setCpu("Intel i7");
    }
    @Override
    public void buildMemory() {
        computer.setMemory("16GB");
    }
    @Override
    public void buildHardDisk() {
        computer.setHardDisk("1TB SSD");
    }
    @Override
    public Computer getComputer() {
        return computer;
    }
}
 
Director(指挥者):ComputerDirector类,负责调用Builder的步骤,控制构建过程。
class ComputerDirector {
    private ComputerBuilder computerBuilder;
    public ComputerDirector(ComputerBuilder computerBuilder) {
        this.computerBuilder = computerBuilder;
    }
    public void constructComputer() {
        computerBuilder.buildCpu();
        computerBuilder.buildMemory();
        computerBuilder.buildHardDisk();
    }
    public Computer getComputer() {
        return computerBuilder.getComputer();
    }
}
 
客户端代码
public class BuilderPatternDemo {
    public static void main(String[] args) {
        ComputerBuilder builder = new GamingComputerBuilder();
        ComputerDirector director = new ComputerDirector(builder);
        director.constructComputer();
        Computer computer = director.getComputer();
        System.out.println(computer);
    }
}
 
链式建造者
流式接口(Fluent Interface)或链式建造者模式。这种方式通过返回this来实现链式调用,代码更加简洁和直观。
 下面是一个使用链式调用的建造者模式示例:
产品类(Computer)
class Computer {
    private String cpu;
    private String memory;
    private String hardDisk;
    private String gpu;
    public void setCpu(String cpu) {
        this.cpu = cpu;
    }
    public void setMemory(String memory) {
        this.memory = memory;
    }
    public void setHardDisk(String hardDisk) {
        this.hardDisk = hardDisk;
    }
    public void setGpu(String gpu) {
        this.gpu = gpu;
    }
    @Override
    public String toString() {
        return "Computer [cpu=" + cpu + ", memory=" + memory + ", hardDisk=" + hardDisk + ", gpu=" + gpu + "]";
    }
}
 
建造者类(ComputerBuilder)
class ComputerBuilder {
    private Computer computer;
    public ComputerBuilder() {
        this.computer = new Computer();
    }
    public ComputerBuilder buildCpu(String cpu) {
        computer.setCpu(cpu);
        return this; // 返回this,支持链式调用
    }
    public ComputerBuilder buildMemory(String memory) {
        computer.setMemory(memory);
        return this; // 返回this,支持链式调用
    }
    public ComputerBuilder buildHardDisk(String hardDisk) {
        computer.setHardDisk(hardDisk);
        return this; // 返回this,支持链式调用
    }
    public ComputerBuilder buildGpu(String gpu) {
        computer.setGpu(gpu);
        return this; // 返回this,支持链式调用
    }
    public Computer build() {
        return computer; // 返回最终构建的对象
    }
}
 
客户端代码
public class BuilderPatternDemo {
    public static void main(String[] args) {
        // 使用链式调用构建对象
        Computer computer = new ComputerBuilder()
                .buildCpu("Intel i7")
                .buildMemory("16GB")
                .buildHardDisk("1TB SSD")
                .buildGpu("NVIDIA RTX 3080")
                .build();
        System.out.println(computer);
    }
}
 
对比传统建造者模式
- 传统建造者模式:通过
Director类控制构建过程,适合构建过程固定的场景。 - 链式建造者模式:通过返回
this实现链式调用,适合构建过程灵活、需要动态配置的场景。 
二、建造者模式在框架源码中的运用
Java中的StringBuilder和StringBuffer
StringBuilder和StringBuffer是Java中用于构建字符串的类,它们使用了类似建造者模式的思想,通过链式调用来逐步构建字符串。
 示例
StringBuilder builder = new StringBuilder();
builder.append("Hello")
       .append(" ")
       .append("World");
String result = builder.toString();
System.out.println(result); // 输出: Hello World
 
- 分析: 
  
append方法返回this,支持链式调用。- 通过逐步构建字符串,最终调用
toString方法生成结果。 
 
Spring Framework中的BeanDefinitionBuilder
在Spring框架中,BeanDefinitionBuilder用于构建BeanDefinition对象,它是Spring IoC容器中定义Bean的核心类。
 示例
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(MyBean.class);
builder.addPropertyValue("name", "MyBeanName")
       .addPropertyValue("age", 30)
       .setScope(BeanDefinition.SCOPE_SINGLETON);
BeanDefinition beanDefinition = builder.getBeanDefinition();
 
- 分析: 
  
BeanDefinitionBuilder通过链式调用逐步配置Bean的属性。- 最终通过
getBeanDefinition方法生成BeanDefinition对象。 
 
三、总结
建造者模式的优点
- 分离构建与表示: 
  
- 将对象的构建过程与表示分离,使得相同的构建过程可以创建不同的表示。
 - 客户端不需要知道对象的具体构建细节。
 
 - 灵活性和可扩展性: 
  
- 可以逐步构建对象,支持动态配置。
 - 新增构建步骤或修改构建顺序非常方便。
 
 - 代码可读性和可维护性: 
  
- 链式调用(
Fluent Interface)使代码更加简洁和直观。 - 将复杂的构建逻辑封装在建造者类中,客户端代码更清晰。
 
 - 链式调用(
 - 避免构造方法参数过多: 
  
- 通过逐步设置属性,避免了构造方法参数过长的问题(
Telescoping Constructor Problem)。 
 - 通过逐步设置属性,避免了构造方法参数过长的问题(
 - 保证对象的一致性: 
  
- 对象在完全构建之前不会被使用,确保对象的一致性和完整性。
 
 
建造者模式的缺点
- 增加代码复杂性: 
  
- 需要额外定义建造者类,增加了类的数量。
 - 对于简单对象,使用建造者模式可能会显得冗余。
 
 - 适用范围有限: 
  
- 适用于构建复杂对象,如果对象属性较少或构建过程简单,使用建造者模式可能会过度设计。
 
 - 性能开销: 
  
- 由于需要创建建造者对象,可能会引入额外的性能开销(通常可以忽略不计)。
 
 
建造者模式的适用场景
- 构建复杂对象: 
  
- 当对象有很多属性,且构建过程复杂时,适合使用建造者模式。
 - 例如,构建一个包含多个配置项的计算机对象。
 
 - 需要多种表示形式: 
  
- 当同一个构建过程需要生成不同的对象表示时,适合使用建造者模式。
 - 例如,构建不同类型的计算机(游戏计算机、办公计算机等)。
 
 - 避免构造方法参数过多: 
  
- 当构造方法参数过多,导致代码难以阅读和维护时,适合使用建造者模式。
 
 - 需要逐步构建对象: 
  
- 当对象的构建过程需要分步骤完成时,适合使用建造者模式。
 - 例如,构建一个
HTTP请求配置对象。 
 - 框架或工具类中的配置对象: 
  
- 在框架或工具类中,经常需要构建复杂的配置对象,建造者模式非常适合这种场景。
 - 例如,Spring中的
BeanDefinitionBuilder、ApacheHttpClient中的RequestConfig.Builder等。 
 
