建造者设计模式(Builder Design Pattern) 是一种 创建型设计模式,它的核心目标是:
将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。
简单说:当你需要创建一个有很多可选参数或步骤的对象时,用建造者模式可以让代码更清晰、安全、易读。
🧱 为什么需要建造者模式?
❌ 问题:传统方式创建复杂对象很痛苦
假设你要创建一个 Product 对象,它有 10 个属性,其中 5 个是可选的:
方式1:多构造函数("重叠构造函数"反模式)
public Product(string name) { ... }
public Product(string name, string color) { ... }
public Product(string name, string color, int size) { ... }
// ... 组合爆炸!难以维护
方式2:setter 方法(但对象可能处于不一致状态)
var product = new Product();
product.Name = "Laptop";
product.Color = "Silver";
// 忘记设置 Price?对象不完整!
方式3:巨型构造函数(参数太多,易错)
new Product("Laptop", "Silver", null, 15, true, false, "Intel", ...); // 谁看得懂?
✅ 建造者模式如何解决?
它引入一个 "建造者(Builder)" 类,提供 链式调用(Fluent Interface) 的方式逐步设置属性,最后调用 Build() 创建最终对象。
🔧 核心角色:
| 角色 | 说明 |
|---|---|
| Product(产品) | 要创建的复杂对象 |
| Builder(抽象建造者) | 定义创建各部分的接口(C# 中常用接口或抽象类) |
| ConcreteBuilder(具体建造者) | 实现 Builder,负责组装 Product |
| Director(指挥者,可选) | 封装固定的构建流程(非必须) |
✅ C# 示例:建造一台电脑
1️⃣ 产品类(不可变推荐)
public class Computer
{
public string CPU { get; }
public string RAM { get; }
public string Storage { get; }
public bool HasGPU { get; }
// 私有构造函数,只能通过 Builder 创建
private Computer(ComputerBuilder builder)
{
CPU = builder.CPU;
RAM = builder.RAM;
Storage = builder.Storage;
HasGPU = builder.HasGPU;
}
// 嵌套 Builder 类(常见做法)
public class Builder
{
public string CPU { get; private set; }
public string RAM { get; private set; }
public string Storage { get; private set; }
public bool HasGPU { get; private set; }
public Builder SetCPU(string cpu)
{
CPU = cpu;
return this; // 支持链式调用
}
public Builder SetRAM(string ram)
{
RAM = ram;
return this;
}
public Builder SetStorage(string storage)
{
Storage = storage;
return this;
}
public Builder WithGPU(bool hasGpu = true)
{
HasGPU = hasGpu;
return this;
}
public Computer Build()
{
// 可在此添加验证逻辑
if (string.IsNullOrEmpty(CPU))
throw new InvalidOperationException("CPU is required");
return new Computer(this);
}
}
}
2️⃣ 使用建造者(清爽!)
var gamingPC = new Computer.Builder()
.SetCPU("Intel i9")
.SetRAM("32GB DDR5")
.SetStorage("2TB NVMe SSD")
.WithGPU(true)
.Build();
var officePC = new Computer.Builder()
.SetCPU("Intel i5")
.SetRAM("16GB DDR4")
.SetStorage("512GB SSD")
// 不调用 WithGPU,默认 false
.Build();
✅ 优点:
- 代码可读性强(像自然语言)
- 参数顺序无关
- 可选参数灵活
- 最终对象可以是不可变的(线程安全)
- 构建过程可加验证
🆚 建造者 vs 其他模式
| 模式 | 适用场景 |
|---|---|
| 建造者(Builder) | 对象有多个可选组成部分,构建过程复杂 |
| 工厂(Factory) | 根据条件创建不同子类实例 (如 CreateCar("BMW")) |
| 原型(Prototype) | 通过复制现有对象来创建新对象 |
💡 建造者关注"怎么一步步构建一个复杂对象 ",工厂关注"该返回哪个具体类型"。
✅ 真实应用场景
-
StringBuilder(名字就体现了!)
var sb = new StringBuilder(); sb.Append("Hello").Append(" ").Append("World"); string result = sb.ToString(); // Build! -
ASP.NET Core 配置
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); builder.Configuration.AddJsonFile("appsettings.json"); var app = builder.Build(); // 最终构建 WebApplication -
HTTP 客户端构建
var client = new HttpClientBuilder() .WithBaseAddress("https://api.example.com") .WithTimeout(TimeSpan.FromSeconds(30)) .WithRetryPolicy(3) .Build(); -
SQL 查询构建器
var query = SqlBuilder.Select("Id, Name") .From("Users") .Where("Age > @age") .OrderBy("Name") .Build();
⚠️ 注意事项
- 不要过度使用:如果对象只有 2~3 个参数,直接用构造函数更简单。
- Builder 类通常作为 Product 的嵌套类(如上面示例),保持封装性。
- 最终对象建议设计为不可变(只读属性),提高安全性。
✅ 小结
| 关键点 | 说明 |
|---|---|
| 目的 | 分离复杂对象的构建与表示 |
| 核心 | 用 Builder 逐步设置属性,最后 Build() |
| 优势 | 链式调用、可读性强、支持可选参数、对象可不可变 |
| 适用 | 对象有很多可选配置项(如配置、文档、UI 组件等 |
问题
使用建造者设计模式的好处是什么?
它允许逐步构建对象,有助于将复杂的构建逻辑封装在单独的类中。
缺点是什么
他需要大量额外的代码,许多构建的类的代码
with关键字有什么作用
它用于创建具有某些特定字段或字段设置为新值的记录副本