示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载Builder构建器模式是 Gang of Four 提出的经典创建型模式之一它允许我们分步骤构造复杂对象并把对象的构造过程与对象的最终表示彻底解耦从而用同一套构造流程产出不同形态的对象。本指南以 java-design-patterns 仓库中builder模块德语文档位于 localization/de/builder/README.md英文原版见 builder/README.md为主线结合 Hero.java、App.java 及对应测试源码完整讲解 Builder 模式的原理、Joshua Bloch 风格实现、参数校验、枚举取值与适用场景读完你即可在自己的 Java 项目中复刻这一套流式fluent构建方案。一、Builder 模式的目的与核心思想Builder 是一个创建型creational模式其核心目的在于将复杂对象的构造过程与其**表示representation**分离使得同一个构造过程可以创建出不同的表示。通俗地说Builder 允许你在**不编写大量重载构造器constructor pollution**的情况下灵活地拼装出同一对象的多种形态尤其适合那些创建过程步骤繁多、或对象存在多种风味组合的场景。真实世界类比定制三明治想象你在熟食店定制一份三明治。你不需要知道三明治内部究竟如何组装只需要通过一个SandwichBuilder一步一步指定想要的组件——面包种类、肉类、奶酪、蔬菜、酱料。构造流程与最终成品分离意味着基于同样的组件可以按不同选择组合出截然不同的三明治。这正是 Builder 模式在现实中的投影使用者只需按步骤声明需求装配细节由构建器封装。一句话概括你可以创建同一对象的多种形态而无需维护一堆构造函数重载或一个参数冗长的构造函数当对象的创建步骤很多、或对象可能出现多种口味时Builder 尤其有用。二、Builder 要解决的痛点Telescoping Constructor 反模式Wikipedia 将 Builder 描述为旨在解决 Telescoping Constructor伸缩构造器反模式的对象创建型设计模式。这个反模式长什么样几乎所有开发者都见过类似的构造函数public Hero(Profession profession, String name, HairType hairType, HairColor hairColor, Armor armor, Weapon weapon){ // 值赋值 }问题显而易见参数数量迅速膨胀难以分辨每个参数的含义与顺序一旦后续新增可选选项参数列表会继续变长为了支持不同参数组合往往还要叠加多层重载形成伸缩式的构造函数金字塔。这就是Telescoping Constructor Antipattern。Builder 模式的使命就是用一个逐步接收初始化参数的构建器对象取代大量构造函数组合最终一次性返回构建完成的对象。构建时序下图展示了 Builder 模式的调用时序图片来源 builder/etc/builder-sequence-diagram.png三、仓库中的程序化示例用 Builder 构建 Hero在 builder 模块 中我们用 Builder 构建带不同属性的Hero对象。场景设定是角色扮演游戏的角色生成器最简单的方式是让计算机全自动生成角色但玩家有时希望手动挑选职业、发色、护甲等属性这个选择过程逐步进行直到所有想要的特征确定下来才算完成。用 Builder 正是更明智的解法。3.1 产品类 Hero仓库中的Hero以Java record形式定义Hero.java字段全部为final不可变对象与 Builder 天然契合public record Hero( Profession profession, String name, HairType hairType, HairColor hairColor, Armor armor, Weapon weapon) { private Hero(Builder builder) { this( builder.profession, builder.name, builder.hairType, builder.hairColor, builder.armor, builder.weapon); } // toString() 及嵌套 Builder 类见下文 }要点私有构造器只接收Builder外部无法绕过 Builder 直接实例化构造时从builder中一次性取走全部六个属性toString()依据非空字段动态拼装描述文本如with ... hair、wearing ...、wielding a ...注意对BALD秃头做了特判输出head而非hair见 Hero.java。3.2 属性枚举可选的取值空间Builder 的可选参数全部来自枚举这为可选项提供了明确的取值范围源码位于 builder/src/main/java/com/iluwatar/builder枚举可取值Profession职业必填WARRIOR、THIEF、MAGE、PRIESTHairType发型可选BALD、SHORT、CURLY、LONG_STRAIGHT、LONG_CURLYHairColor发色可选WHITE、BLOND、RED、BROWN、BLACKArmor护甲可选CLOTHES、LEATHER、CHAIN_MAIL、PLATE_MAILWeapon武器可选DAGGER、SWORD、AXE、WARHAMMER、BOW其中HairType与Armor通过 Lombok 的AllArgsConstructor注入展示用标题文本如chain mail并重写toString()返回小写可读形式Profession、HairColor、Weapon则直接以枚举名小写作为展示文本。3.3 嵌套 BuilderJoshua Bloch 风格Hero.Builder是Hero的静态嵌套类Hero.java采用了《Effective Java》第二版中 Joshua Bloch 推荐的实现变体。模块入口 App.java 的 Javadoc 明确说明了这一点并指出 Builder 的另一大优势它非常适合构造扁平数据型对象如 HTML 代码、SQL 查询、X.509 证书等——这类数据无法逐步编辑、必须一次性给出用 Builder 类构造是最佳途径。public static class Builder { private final Profession profession; // 必填final private final String name; // 必填final private HairType hairType; // 可选可变 private HairColor hairColor; // 可选可变 private Armor armor; // 可选可变 private Weapon weapon; // 可选可变 public Builder(Profession profession, String name) { if (profession null || name null) { throw new IllegalArgumentException(profession and name can not be null); } this.profession profession; this.name name; } public Builder withHairType(HairType hairType) { this.hairType hairType; return this; } public Builder withHairColor(HairColor hairColor) { this.hairColor hairColor; return this; } public Builder withArmor(Armor armor) { this.armor armor; return this; } public Builder withWeapon(Weapon weapon) { this.weapon weapon; return this; } public Hero build() { return new Hero(this); } }这套实现蕴含的规范要点必填参数进构造器profession与name必须在new Hero.Builder(...)时提供且被声明为final从机制上杜绝忘填必填项构造器内即校验任一必填参数为null时立即抛出IllegalArgumentException(profession and name can not be null)实现快速失败fail-fast可选参数用流式方法每个withXxx方法设置字段后返回this支持链式调用fluent interfacebuild()收尾一次性调用私有构造器生成不可变的Hero实例。3.4 使用示例与程序输出App.java 演示了三种角色的构建public static void main(String[] args) { var mage new Hero.Builder(Profession.MAGE, Riobard) .withHairColor(HairColor.BLACK) .withWeapon(Weapon.DAGGER) .build(); LOGGER.info(mage.toString()); var warrior new Hero.Builder(Profession.WARRIOR, Amberjill) .withHairColor(HairColor.BLOND) .withHairType(HairType.LONG_CURLY) .withArmor(Armor.CHAIN_MAIL) .withWeapon(Weapon.SWORD) .build(); LOGGER.info(warrior.toString()); var thief new Hero.Builder(Profession.THIEF, Desmond) .withHairType(HairType.BALD) .withWeapon(Weapon.BOW) .build(); LOGGER.info(thief.toString()); }注意三者对可选属性的取舍各不相同——mage 只配置了发色与武器warrior 配齐全部四项thief 则只选了发型与武器——这正是同一个构造过程产出不同表示的直观体现。程序输出经由Slf4j注入的LOGGER打印16:28:06.058 [main] INFO com.iluwatar.builder.App -- This is a mage named Riobard with black hair and wielding a dagger. 16:28:06.060 [main] INFO com.iluwatar.builder.App -- This is a warrior named Amberjill with blond long curly hair wearing chain mail and wielding a sword. 16:28:06.060 [main] INFO com.iluwatar.builder.App -- This is a thief named Desmond with bald head and wielding a bow.3.5 测试验证仓库测试从两个维度保证了模式实现的行为正确性HeroTest.javatestMissingProfession/testMissingName验证必填参数校验——传入null职业或null名字都会触发IllegalArgumentExceptionHeroTest.javatestBuildHero构建一个全属性 WarriorSir Lancelot逐项断言profession()、name()、armor()、weapon()、hairType()、hairColor()与构建请求一致HeroTest.java印证了构建器忠实反映所有请求属性的契约AppTest.java验证App.main执行全程不抛异常。3.6 类结构一览builder模块的 UML 类图PlantUML 源文件见 builder/etc/builder.urm.puml展示了整体结构Hero聚合六个属性字段并依赖嵌套BuilderBuilder .. HeroBuilder与五个枚举分别关联。该模块pom.xml位于 builder/pom.xml可通过项目根目录的./mvnw在builder模块下运行./mvnw -pl builder test或直接运行App复现上述输出。四、适用场景什么时候使用 Builder综合文档与实现当以下条件成立时 Builder 是最佳选择应用需要复杂对象的构造构造函数参数繁多复杂对象的构造算法应独立于其组成部分以及这些部分的组装方式构造过程必须允许产出所构造对象的不同表示特别适用于创建步骤多、且步骤需要按特定顺序执行的场景对象为不可变设计、或包含扁平数据一次性成型的 HTML/SQL/X.509 等时Builder 几乎是最优解。五、Java 生态中的真实应用Builder 在 JDK 与主流框架中随处可见以下均为文档列出的知名实例可结合 builder/README.md 原文查看StringBuilder与StringBuffer逐步构造可变字符串对象java.nio.ByteBuffer及FloatBuffer、IntBuffer等缓冲区类javax.swing.GroupLayout.Group#addComponent()IDE 中的各类 GUI 构建器用于组装 UI 组件所有java.lang.Appendable的实现类Apache Camel 的 builder 工具集Apache Commons CLI 的Option.Builder。六、优点与代价优点Benefits相比其他创建型模式对构造过程有更强的控制力支持逐步构造、延迟构造步骤、甚至递归执行步骤可以构造需要复杂子对象组装的对象最终产品与其组成部分及组装过程完全解耦符合单一职责原则SRP复杂的构造代码可与产品的业务逻辑隔离。代价Trade-offs由于需要新增 Builder 类整体代码复杂度可能上升构建过程中创建的多个 Builder 对象可能增加内存占用。七、与其他模式的关系Abstract Factory可与 Builder 协同使用由抽象工厂生成复杂对象的各个部分PrototypeBuilder 常常基于原型来创建对象Step BuilderBuilder 的一种变体采用逐步step-by-step方式生成复杂对象当对象拥有大量可选参数、且希望规避 Telescoping Constructor 反模式时Step Builder 是很好的选择。八、参考与延伸阅读本文依据的德语文档与英文原版在 localization/de/builder/README.md、builder/README.md涉及源码集中在 builder/src/main/java/com/iluwatar/builder。模式的理论源头可追溯至《Design Patterns: Elements of Reusable Object-Oriented Software》GoF 著、《Effective Java》Joshua Bloch本书正是仓库该实现变体的出处、《Head First Design Patterns》与《Refactoring to Patterns》等经典著作。小结在 java-design-patterns 仓库的builder模块中Builder 模式以必填参数入构造器 可选参数流式链 构造时校验 不可变产品的完整形态落地。对照 Hero.java 与 HeroTest.java 逐行研读即可将这套模式迁移到任何参数多、可选性强、追求不可变的 Java 业务对象上。赞分享示例工程教程【免费下载链接】java-design-patternsDesign patterns implemented in Java项目地址https://gitcode.com/GitHub_Trending/ja/java-design-patterns点击查看免费下载相关推荐Java 设计模式之 Builder建造者模式java-design-patterns 仓库中的 Hero 构建实战Java 设计模式之 Builder建造者模式java design patterns 仓库中的 Hero 构建实战 Builder建造者模式是 Ja示例工程教程Java Builder 模式实战以 java-design-patterns 的 Hero 构建为例彻底告别构造器污染Java Builder 模式实战以 java design patterns 的 Hero 构建为例彻底告别构造器污染 Builder建造者模式是 Go示例工程教程AutoAgent 接入 OpenRouter通过 LiteLLM 统一网关配置 DeepSeek-R1 等聚合模型的完整指南AutoAgent 接入 OpenRouter通过 LiteLLM 统一网关配置 DeepSeek R1 等聚合模型的完整指南 OpenRouter 是一个聚示例工程教程上一篇Repomix 隐私策略深度解析CLI、网站与浏览器扩展的数据处理边界下一篇Taichi RFC 解读AOT 支持所有 SNode——SNode 树类型化与字段本地化的设计之路创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考