欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 国际 > 设计模式——建造者设计模式(创建型)

设计模式——建造者设计模式(创建型)

2025/6/28 8:58:00 来源:https://blog.csdn.net/weixin_41605937/article/details/148356111  浏览:    关键词:设计模式——建造者设计模式(创建型)

摘要

本文详细介绍了建造者设计模式,这是一种创建型设计模式,旨在将复杂对象的构建过程与其表示分离,便于创建不同表示。文中阐述了其设计意图,如隐藏创建细节、提升代码可读性和可维护性,并通过构建电脑的示例加以说明。接着展示了建造者模式的结构,包括抽象建造者、具体建造者、指挥者和产品角色。还提供了 Java 实现示例,分析了其特点与好处,探讨了适用场景,包括适合与不适合的情况,并通过风控请求类的实战示例展示了其优势。最后,提出了结合责任链与建造者构建不同风险场景组合的思考方向。

1. 建造者设计模式定义

建造者模式是一种创建型设计模式,用于将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。定义总结:将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的对象。

1.1. 🧠 设计意图:

  • 屏蔽对象创建的细节,客户端不需要知道构建步骤。
  • 提高代码的可读性、可维护性。
  • 不同建造者构建不同产品,便于扩展。

1.2. 📝 举例说明:

假设我们要构建一台电脑,电脑由 CPU、内存、硬盘等多个部分组成,如果不使用建造者模式,每次创建电脑都要手动写出完整流程,容易出错。使用建造者模式之后,我们可以:

  • 定义不同的建造者(如 GamingComputerBuilderOfficeComputerBuilder)。
  • 使用统一的构建流程(由 Director 控制)生成对应配置的电脑对象。

2. 建造者设计模式结构

2.1. 建造者设计模式类图

建造者模式包含如下角色:

  • Builder:抽象建造者
  • ConcreteBuilder:具体建造者
  • Director:指挥者
  • Product:产品角色

2.2. 建造者设计模式时序图

3. 建造者设计模式实现方式

3.1. ✅ Java 实现示例(以构建一台电脑为例)

3.1.1. 产品类(Product)

public class Computer {private String cpu;private String memory;private String storage;// setterpublic void setCpu(String cpu) { this.cpu = cpu; }public void setMemory(String memory) { this.memory = memory; }public void setStorage(String storage) { this.storage = storage; }@Overridepublic String toString() {return "Computer [CPU=" + cpu + ", Memory=" + memory + ", Storage=" + storage + "]";}
}

3.1.2. 抽象建造者(Builder)

public interface ComputerBuilder {void buildCpu();void buildMemory();void buildStorage();Computer getComputer();
}

3.1.3. 具体建造者(ConcreteBuilder)

public class GamingComputerBuilder implements ComputerBuilder {private Computer computer = new Computer();@Overridepublic void buildCpu() {computer.setCpu("Intel i9");}@Overridepublic void buildMemory() {computer.setMemory("32GB DDR5");}@Overridepublic void buildStorage() {computer.setStorage("2TB SSD");}@Overridepublic Computer getComputer() {return computer;}
}

3.1.4. 指挥者(Director)

public class ComputerDirector {public Computer construct(ComputerBuilder builder) {builder.buildCpu();builder.buildMemory();builder.buildStorage();return builder.getComputer();}
}

3.1.5. 客户端(Client)

public class Main {public static void main(String[] args) {ComputerBuilder builder = new GamingComputerBuilder();ComputerDirector director = new ComputerDirector();Computer computer = director.construct(builder);System.out.println(computer);}
}

3.2. 🧠 建造者设计模式特点与好处

  • 将构建过程与表示解耦,提高灵活性
  • 更适合构建复杂对象或多步骤构建的对象
  • 客户端无需关心细节,适配不同场景(如游戏电脑、办公电脑)

4. 建造者设计模式适合场景

4.1. ✅ 建造者设计模式适合的场景

场景描述

举例说明

对象构建复杂,包含多个可选或必须参数、或有构建顺序要求

如一台电脑需设置 CPU、内存、硬盘等,并按照一定顺序构造

同一个构建过程,生成不同表现形式的对象

如根据配置构建不同风格的 UI 界面,或生成不同类型的报表(PDF/HTML/Excel)

希望封装构建过程,将构建与表示分离,构建逻辑复杂

如报文协议构建、SQL 语句构建、复杂 HTTP 请求构建等

需要一步一步构建对象,各步骤可自由组合/复用

如订单生成流程、商品 SKU 属性配置流程等

希望在创建对象时不直接暴露其创建逻辑,而是通过统一接口进行构建

Spring 中的 RestTemplateBuilderHttpClientBuilder

4.2. ❌ 不适合使用建造者模式的场景

场景描述

原因说明

1️⃣ 对象结构简单,参数少或构建过程简单

使用构造函数或静态工厂方法即可,无需引入复杂建造者类

2️⃣ 对象变化频繁,构建逻辑变化快且不可复用

每次变化都要修改建造者结构,维护成本高

3️⃣ 需要一次性创建大量简单对象

建造者模式对象构建慢,效率低,适合复杂对象

4️⃣ 创建对象不涉及多个步骤或步骤之间没有顺序依赖

可以直接使用构造器重载或 @Builder注解

4.3. ✅ 示例对比

4.3.1. ✔ 适合建造者模式的示例

User user = new UserBuilder().setName("张三").setAge(30).setEmail("zhangsan@example.com").build();

4.3.2. ❌ 不适合建造者模式的示例(对象简单)

User user = new User("张三", 30); // 直接构造函数更简单

5. 建造者设计模式实战示例

以下是一个 建造者设计模式在 Spring 项目中用于金融风控场景 的实战示例,场景描述为:构建一个复杂的风控请求对象 RiskRequest,该对象包含多个字段、可能依赖外部配置、构建顺序有要求,并且需要灵活组合。

5.1. 🌟 场景背景

在金融风控系统中,需要对接多个风控策略服务,而每次调用前都需构造复杂的风控请求体 RiskRequest,其字段包括用户、交易、设备、地理位置、行为历史等,字段较多、部分字段可选、构建过程复杂。

5.2. 🧱 建造者模式结构设计

5.2.1. 风控请求类 RiskRequest

public class RiskRequest {private String userId;private String ip;private String deviceId;private String location;private BigDecimal amount;private String channel;private Map<String, Object> extension;// 私有构造器,避免外部直接 newprivate RiskRequest() {}// Getter 省略public static class Builder {private final RiskRequest request = new RiskRequest();public Builder userId(String userId) {request.userId = userId;return this;}public Builder ip(String ip) {request.ip = ip;return this;}public Builder deviceId(String deviceId) {request.deviceId = deviceId;return this;}public Builder location(String location) {request.location = location;return this;}public Builder amount(BigDecimal amount) {request.amount = amount;return this;}public Builder channel(String channel) {request.channel = channel;return this;}public Builder extension(Map<String, Object> ext) {request.extension = ext;return this;}public RiskRequest build() {// 可添加参数校验逻辑return request;}}
}

5.2.2. Spring 风控服务中使用

@Service
public class RiskEngineService {public RiskResult assessRisk(TransactionContext ctx) {RiskRequest request = new RiskRequest.Builder().userId(ctx.getUserId()).ip(ctx.getIp()).deviceId(ctx.getDeviceId()).location(ctx.getLocation()).amount(ctx.getAmount()).channel("APP").extension(Map.of("loginTime", ctx.getLoginTime())).build();// 调用远程风控引擎return remoteRiskClient.invoke(request);}
}

5.3. ✅ 优势分析

维度

表现

可读性

.xxx().xxx()

链式构建清晰易读

可维护性

字段变更不影响业务逻辑代码,只需改 builder

可扩展性

可灵活扩展参数、做默认值处理

解耦

业务逻辑和构建逻辑分离,保持 Service 层简洁

5.4. 🔄 延伸:结合 Lombok 简化构建(若字段不太复杂)

@Data
@Builder
public class RiskRequest {private String userId;private String ip;private String deviceId;private String location;private BigDecimal amount;private String channel;private Map<String, Object> extension;
}

然后直接用:

RiskRequest request = RiskRequest.builder().userId("u123").ip("192.168.1.1").amount(new BigDecimal("999.00")).build();

6. 建造者设计模式思考

6.1. 结合责任链+建造者构建不同风险场景组合?

结合 责任链(Chain of Responsibility)+ 建造者模式(Builder Pattern),可以优雅地解决金融风控场景中 构建复杂请求对象时的多变逻辑组合问题

6.1.1. 📌 背景场景

你在构建 RiskRequest 时,可能存在如下 变化点

  • 不同业务线(信贷、支付、转账)关注字段不同;
  • 不同渠道(APP、小程序、Web)获取数据来源不同;
  • 某些字段需要动态计算(如 IP 解析地理位置);
  • 某些字段需要兜底或配置中心取默认值。

这些都很适合通过责任链机制 按模块职责划分建造逻辑,结合建造者模式,按步骤组合构建一个完整对象。

6.1.2. 🧱 设计结构图

RiskRequestBuilder├── RiskBuildHandlerA(构建用户信息)├── RiskBuildHandlerB(构建设备信息)├── RiskBuildHandlerC(构建交易信息)├── RiskBuildHandlerD(构建位置信息)└── RiskBuildHandlerX(扩展字段...)

6.1.3. ✅ 风控请求实体 + Builder

public class RiskRequest {private String userId;private String ip;private String location;private BigDecimal amount;private Map<String, Object> ext;private RiskRequest() {}public static class Builder {private final RiskRequest request = new RiskRequest();public Builder userId(String userId) {request.userId = userId; return this;}public Builder ip(String ip) {request.ip = ip; return this;}public Builder location(String location) {request.location = location; return this;}public Builder amount(BigDecimal amount) {request.amount = amount; return this;}public Builder ext(Map<String, Object> ext) {request.ext = ext; return this;}public RiskRequest build() {return request;}}
}

6.1.4. ✅ 定义责任链接口

public interface RiskRequestBuilderHandler {void handle(RiskRequest.Builder builder, RiskContext context);
}

6.1.5. ✅ 各构建器实现类(每个负责构建一部分)

@Component
public class UserInfoBuilderHandler implements RiskRequestBuilderHandler {public void handle(RiskRequest.Builder builder, RiskContext context) {builder.userId(context.getUserId());}
}@Component
public class IpInfoBuilderHandler implements RiskRequestBuilderHandler {public void handle(RiskRequest.Builder builder, RiskContext context) {builder.ip(context.getIp());}
}@Component
public class LocationBuilderHandler implements RiskRequestBuilderHandler {public void handle(RiskRequest.Builder builder, RiskContext context) {// 可通过 IP 反查地址builder.location("Shanghai"); // 示例}
}

6.1.6. ✅ 构建入口类(责任链容器)

@Component
public class RiskRequestDirector {@Autowiredprivate List<RiskRequestBuilderHandler> handlers;public RiskRequest build(RiskContext context) {RiskRequest.Builder builder = new RiskRequest.Builder();for (RiskRequestBuilderHandler handler : handlers) {handler.handle(builder, context);}return builder.build();}
}

✅ Spring 会自动注入所有 RiskRequestBuilderHandler,实现责任链顺序处理(可用 @Order 控制顺序)

6.1.7. ✅ 风控服务中使用

@Service
public class RiskService {@Autowiredprivate RiskRequestDirector requestDirector;public RiskResult runRisk(TransactionContext ctx) {RiskContext riskContext = convert(ctx);RiskRequest request = requestDirector.build(riskContext);return remoteRiskClient.invoke(request);}
}

6.2. 🌟 责任链+建造者总结

描述

解耦构建逻辑

每个字段构建逻辑拆分为独立模块

符合开闭原则

新增构建字段不影响已有代码

动态适配

可结合配置中心动态选择构建器链

更适合扩展

支持多业务场景、策略组装、Mock 等

6.3. 🔧 可扩展方向

  • 支持责任链动态配置(按业务线、渠道等匹配);
  • 风控字段来源插件化(支持 SPI 加载数据构建器);
  • 构建失败字段日志审计(异常处理链);
  • 抽象为风控建模平台中的组件。

博文参考

  • 建造者设计模式(生成器模式)
  • 创建型 - 生成器(Builder) | Java 全栈知识体系
  • 4. 建造者模式 — Graphic Design Patterns

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词