【设计模式】建造者模式

发布于:2025-08-09 ⋅ 阅读:(18) ⋅ 点赞:(0)

建造者模式(Builder Pattern)详解


一、建造者模式简介

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

你可以这样理解:

“建造者模式就像搭积木,你可以用相同的步骤(如:打地基 → 盖墙 → 装屋顶)来建造不同的房子(别墅、公寓、仓库)。”

它特别适用于构造过程稳定但内部组成多变的复杂对象。

将客户端与包含多个部件的复杂对象的创建过程分离,客户端无须知道复杂对象的内部组成部分与装配方式,只需要知道所需建造者的类型即可。
关注如何逐步创建一个复杂的对象,不同的建造者定义了不同的创建过程。

建造者模式包含以下4个角色
Builder(抽象建造者)
ConcreteBuilder(具体建造者)
Product(产品)
Director(指挥者)

在这里插入图片描述


二、解决的问题类型

建造者模式主要用于解决以下问题:

  • 对象构造过程复杂,参数众多,尤其是存在可选参数时,使用 new 或构造函数会变得难以维护。
  • 需要创建的对象具有多种组合形式,但构建流程一致。
  • 避免“伸缩构造器反模式”(Telescoping Constructor Pattern):即定义多个参数数量不同的构造函数。

三、使用场景

场景 示例
创建复杂对象 StringBuilderHttp请求对象SQL查询对象
配置对象初始化 OkHttpClientRetrofitThreadPoolExecutor
UI组件构建 如 Android 中的 AlertDialog.Builder
领域模型构建 如订单、用户信息等含多个可选字段的对象

需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员变量。
需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
对象的创建过程独立于创建该对象的类。在建造者模式中通过引入了指挥者类,将创建过程封装在指挥者类中,而不在建造者类和客户类中。
隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。


四、核心概念

  1. Product(产品类):要创建的复杂对象。
  2. Builder(抽象建造者):定义创建产品各个部件的抽象接口。
  3. ConcreteBuilder(具体建造者):实现 Builder 接口,提供具体构建逻辑。
  4. Director(指挥者):负责调用建造者对象的构建步骤,控制流程(可选,在Java中常被省略,由客户端直接调用)。
  5. Client(客户端):创建建造者对象并逐步设置参数,最终生成产品。

五、实际代码案例(Java)

我们以“电脑(Computer)”的组装为例,演示建造者模式的使用。

1. 定义产品类:Computer

// 电脑产品类
public class Computer {
    private String cpu;
    private String ram;
    private String storage;
    private String gpu;
    private boolean hasBluetooth;
    private boolean hasWifi;

    // 私有构造函数,只能由 Builder 创建
    private Computer(Builder builder) {
        this.cpu = builder.cpu;
        this.ram = builder.ram;
        this.storage = builder.storage;
        this.gpu = builder.gpu;
        this.hasBluetooth = builder.hasBluetooth;
        this.hasWifi = builder.hasWifi;
    }

    @Override
    public String toString() {
        return "Computer{" +
                "cpu='" + cpu + '\'' +
                ", ram='" + ram + '\'' +
                ", storage='" + storage + '\'' +
                ", gpu='" + gpu + '\'' +
                ", hasBluetooth=" + hasBluetooth +
                ", hasWifi=" + hasWifi +
                '}';
    }

    // 静态内部类 Builder
    public static class Builder {
        // 必填参数
        private String cpu;
        private String ram;
        private String storage;

        // 可选参数(默认值)
        private String gpu = "集成显卡";
        private boolean hasBluetooth = false;
        private boolean hasWifi = true;

        // 构造函数:必填参数
        public Builder(String cpu, String ram, String storage) {
            this.cpu = cpu;
            this.ram = ram;
            this.storage = storage;
        }

        // 设置可选参数的方法(链式调用)
        public Builder setGpu(String gpu) {
            this.gpu = gpu;
            return this;
        }

        public Builder setHasBluetooth(boolean hasBluetooth) {
            this.hasBluetooth = hasBluetooth;
            return this;
        }

        public Builder setHasWifi(boolean hasWifi) {
            this.hasWifi = hasWifi;
            return this;
        }

        // 构建最终对象
        public Computer build() {
            return new Computer(this);
        }
    }
}

2. 客户端测试类

public class Client {
    public static void main(String[] args) {
        // 场景1:组装一台游戏电脑
        Computer gamingPC = new Computer.Builder("i7", "32GB", "1TB SSD")
                .setGpu("RTX 4080")
                .setHasBluetooth(true)
                .setHasWifi(true)
                .build();

        System.out.println("🎮 游戏电脑配置:");
        System.out.println(gamingPC);

        System.out.println();

        // 场景2:组装一台办公笔记本
        Computer officeLaptop = new Computer.Builder("i5", "16GB", "512GB SSD")
                .setGpu("集成显卡")  // 可省略,默认就是集成显卡
                .setHasBluetooth(true)
                .setHasWifi(true)
                .build();

        System.out.println("💼 办公笔记本配置:");
        System.out.println(officeLaptop);

        System.out.println();

        // 场景3:极简配置(只填必填项)
        Computer basicPC = new Computer.Builder("i3", "8GB", "256GB SSD").build();
        System.out.println("📦 基础电脑配置:");
        System.out.println(basicPC);
    }
}

输出结果:

🎮 游戏电脑配置:
Computer{cpu='i7', ram='32GB', storage='1TB SSD', gpu='RTX 4080', hasBluetooth=true, hasWifi=true}

💼 办公笔记本配置:
Computer{cpu='i5', ram='16GB', storage='512GB SSD', gpu='集成显卡', hasBluetooth=true, hasWifi=true}

📦 基础电脑配置:
Computer{cpu='i3', ram='8GB', storage='256GB SSD', gpu='集成显卡', hasBluetooth=false, hasWifi=true}

典型代码

典型的复杂对象类代码:

class Product
{
private string partA; //定义部件,部件可以是任意类型,包括值类型和引用类型
private string partB;
private string partC;
public string PartA
{
        get { return partA; }
        set { partA = value; }
    }
    public string PartB
    {
        get { return partB; }
        set { partB = value; }
    }
    public string PartC
    {
        get { return partC; }
        set { partC = value; }
    }
}

典型的抽象建造者类代码:

abstract class Builder
{
    //创建产品对象
    protected Product product = new Product();
    public abstract void BuildPartA();
    public abstract void BuildPartB();
    public abstract void BuildPartC();
    //返回产品对象
    public Product GetResult()
    {
        return product;
    }
}

典型的具体建造者类代码:

class ConcreteBuilder1 : Builder
{
    public override void BuildPartA()
    {
        product.PartA = "A1";
    }
    public override void BuildPartB()
    {
        product.PartB = "B1";
    }
    public override void BuildPartC()
    {
        product.PartC = "C1";
    }
}

典型的指挥者类代码:

class Director
{
    private Builder builder;
    public Director(Builder builder)
   {
        this.builder = builder;
    }
    public void SetBuilder(Builder builder)
    {
        this.builder = builder;
    }
    //产品构建与组装方法
    public Product Construct()
    {
        builder.BuildPartA();
        builder.BuildPartB();
        builder.BuildPartC();
        return builder.GetResult();
    }
}

客户类代码片段:

……
Builder builder = new ConcreteBuilder1(); //可通过配置文件实现
Director director = new Director(builder);
Product product = director.Construct();
……

其他案例

  1. 某游戏软件公司决定开发一款基于角色扮演的多人在线网络游戏,玩家可以在游戏中扮演虚拟世界中的一个特定角色,角色根据不同的游戏情节和统计数据(例如力量、魔法、技能等)具有不同的能力,角色也会随着不断升级而拥有更加强大的能力。
    作为该游戏的一个重要组成部分,需要对游戏角色进行设计,而且随着该游戏的升级将不断增加新的角色。通过分析发现,游戏角色是一个复杂对象,它包含性别、面容等多个组成部分,不同类型的游戏角色,其性别、面容、服装、发型等外部特性都有所差异,例如“天使”拥有美丽的面容和披肩的长发,并身穿一袭白裙;而“恶魔”极其丑陋,留着光头并穿一件刺眼的黑衣。
    无论是何种造型的游戏角色,它的创建步骤都大同小异,都需要逐步创建其组成部分,再将各组成部分装配成一个完整的游戏角色。现使用建造者模式来实现游戏角色的创建。

在这里插入图片描述
2. KFC套餐
建造者模式可以用于描述KFC如何创建套餐:套餐是一个复杂对象,它一般包含主食(如汉堡、鸡肉卷等)和饮料(如果汁、可乐等)等组成部分,不同的套餐有不同的组成部分,而KFC的服务员可以根据顾客的要求,一步一步装配这些组成部分,构造一份完整的套餐,然后返回给顾客。

在这里插入图片描述


六、优缺点分析

优点 描述
代码可读性强 链式调用清晰表达对象构建意图
灵活性高 可自由组合可选参数,无需重载多个构造函数
封装性好 产品类构造函数私有,对象一旦创建不可变(可实现不可变对象)
符合单一职责和开闭原则 构建逻辑集中在 Builder 中,易于扩展
缺点 描述
代码量增加 需要额外编写 Builder 类,类结构变复杂
适合属性较多的场景 如果对象属性很少,使用 Builder 反而显得繁琐
构建过程与表示耦合 虽然流程解耦,但 Builder 仍与 Product 类紧密关联

七、与工厂模式对比

对比点 建造者模式 工厂模式
目的 构建复杂对象,强调构建过程 创建对象,强调创建结果
适用对象 内部结构复杂、参数多的对象 结构相对简单的对象
使用方式 分步设置参数,最后 build() 一次性传参创建
典型应用 StringBuilder, AlertDialog.Builder Calendar.getInstance()

八、最终小结

建造者模式是一种非常实用且优雅的设计模式,特别适合用于创建参数多、有必填/可选字段、构造过程复杂的对象。它通过链式调用的方式,让对象的创建过程变得直观、清晰、易于维护。

在设计 API、构建配置类、处理复杂 DTO 或领域模型时,建造者模式是一个非常值得掌握的工具。许多主流框架(如 Lombok 的 @Builder 注解)也提供了对建造者模式的便捷支持。


📌 一句话总结:

建造者模式就像“定制套餐”,你可以一步步选择想要的配置,最后“下单”生成一个完整的对象。


推荐使用场景:

  • 类的构造函数参数超过 4 个;
  • 参数中包含多个可选字段;
  • 需要保证对象创建过程的顺序或一致性;
  • 希望提升代码的可读性和可维护性。

💡 小贴士:可以使用 Lombok 的 @Builder 注解自动生成 Builder 代码,减少样板代码。

@Builder
public class User {
    private String name;
    private int age;
    private String email;
    private boolean isActive;
}
// 使用:User user = User.builder().name("Tom").age(25).build();

以上部分内容由AI大模型生成,注意识别!


网站公告

今日签到

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