news 2026/10/12 1:42:58

设计模式学习(7) 23-5 建造者模式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
设计模式学习(7) 23-5 建造者模式

文章目录

  • 0.个人感悟
  • 建造者模式
    • 1. 概念
    • 2. 适配场景(什么场景下使用)
    • 3. 实现方法
      • 3.1 实现思路
      • 3.2 UML类图
    • 4. 代码示例
    • 5. 优缺点
    • 6. 源码分析-JDK中的StringBuilder实现分析
    • 7. vs抽象工厂模式

0.个人感悟

  • 建造者模式也是很典型的创建型设计模式。主要目的是将对象的构建和表示分离:构建角色就负责构建过程(建造者 指挥者),对象(产品)只表示自身属性
  • 建造者模式很能表现编程的一个思想:面向接口编程。我们面向对象来建模,抽取不同的角色进行分工,角色和角色之间依赖抽象,方便具体实现的替换,比如这里的具体建造者
  • 截止到目前,创建型设计模式复习完了。整体而言,目的都是创建对象,根据不同的情况来选择不同的模式,从而尽量达到1核(高内聚低耦合)4性(复用性 可读性 维护性 稳定性)7大原则(设计原则)
  • 建造者模式很容易联想到链式调用,比如常用的lombok @Builder注解,可以提高开发效率,有兴趣可以详细了解下原理和使用方法
  • 建议实际工作中多尝试使用设计模式,不怕犯错
  • 祝大家元旦快乐

建造者模式

1. 概念

英文定义(摘自《设计模式:可复用面向对象软件的基础》):

Separate the construction of a complex object from its representation so that the same construction process can create different representations.

中文翻译:

将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。

理解:

  • 将复杂对象的构建过程与最终产品解耦

2. 适配场景(什么场景下使用)

适合的场景:

  1. 创建复杂对象: 当对象包含多个组成部分,且这些部分需要按特定顺序或规则组合时
  2. 构建过程需要精细化控制: 需要分步骤、分阶段构建对象,且构建过程可能变化
  3. 产品有多个变体: 同一个构建过程需要产生不同表示的产品
  4. 分工合作:产品的创建和产品的使用由不同的模块、责任人负责,天然契合建造者模式

常见的具体场景举例:

  • 配置对象的构建(如数据库连接配置)
  • 文档生成器(HTML、PDF等不同格式)
  • 套餐组合
  • 复杂查询构建
  • 游戏角色创建系统

3. 实现方法

3.1 实现思路

  • 分离关注点: 构建过程由指挥者(Director)控制,具体构建由建造者(Builder)实现
  • 构建与表示分离: 同样的构建步骤可以产生不同的产品表示
  • 分步构建: 允许分步骤、精细化地构建复杂对象
  • 控制反转: 客户端不直接创建对象,而是通过指挥者间接创建

3.2 UML类图

  • 产品(Product): 创建要构建的复杂对象,包含所有组成部分
  • 建造者接口(Builder): 声明创建产品各个部分的抽象方法
  • 具体建造者类(ConcreteBuilder):
    • 实现Builder接口
    • 维护当前产品的表示
    • 提供获取最终产品的方法
  • 指挥者(Director):
    • 封装构建过程
    • 使用Builder接口逐步构建产品
  • 客户端: 客户端创建具体建造者,将其传递给指挥者,然后获取最终产品

4. 代码示例

以互联网大厂夜宵文化为例:,简化一下流程,规定夜宵套餐包含 水果 饮料 主食,忽略金额

产品类:

publicclassNightSnack{privateStringfruit;privateStringdrink;privateStringstapleFood;publicStringgetFruit(){returnfruit;}// 省略}

建造者类族:

// 1.抽象建造者publicabstractclassSnackBuilder{NightSnacknightSnack=newNightSnack();publicabstractvoidbuildFruit();publicabstractvoidbuildDrink();publicabstractvoidbuildStapleFood();publicNightSnackgetNightSnack(){returnnightSnack;}}// 2.指挥者publicclassSnackStall{privateSnackBuildersnackBuilder;publicSnackStall(SnackBuildersnackBuilder){this.snackBuilder=snackBuilder;}publicNightSnackconstruct(){// 水果snackBuilder.buildFruit();// 饮料snackBuilder.buildDrink();// 主食snackBuilder.buildStapleFood();returnsnackBuilder.getNightSnack();}}// 3.具体建造者 套餐ApublicclassSnackAextendsSnackBuilder{@OverridepublicvoidbuildFruit(){nightSnack.setFruit("西瓜一个");}@OverridepublicvoidbuildDrink(){nightSnack.setDrink("可乐一瓶");}@OverridepublicvoidbuildStapleFood(){nightSnack.setStapleFood("螺蛳粉一碗");}}// 4.具体建造者 套餐BpublicclassSnackBextendsSnackBuilder{@OverridepublicvoidbuildFruit(){nightSnack.setFruit("酸橘子一筐");}@OverridepublicvoidbuildDrink(){nightSnack.setDrink("外星人饮品一瓶");}@OverridepublicvoidbuildStapleFood(){nightSnack.setStapleFood("面包一块");}}

客户端:

publicclassClient{staticvoidmain(){SnackBuildersnackBuilder=newSnackA();// 这里可以进行套餐更换SnackStallsnackStall=newSnackStall(snackBuilder);NightSnacknightSnack=snackStall.construct();System.out.println(STR."套餐内容: \{nightSnack.getFruit()} \{nightSnack.getDrink()} \{nightSnack.getStapleFood()}");}}

5. 优缺点

结合1核(高内聚低耦合)4性(复用性 可读性 维护性 稳定性)7大原则(设计原则):
优点:

  1. 高内聚低耦合
    • 构建过程封装在指挥者中,与具体建造者解耦
    • 产品与构建过程分离,符合单一职责原则
  2. 复用性
    • 同样的构建过程可以创建不同表示的产品
    • 指挥者代码可以复用,支持不同建造者
  3. 可读性
    • 分步骤构建,逻辑清晰
  4. 维护性
    • 新增产品变体只需添加新的建造者,无需修改现有代码
    • 符合开闭原则
  5. 稳定性
    • 可以确保产品的完整性,避免构建不完整的对象
    • 构建过程可控,减少错误

缺点:

  1. 复杂度增加
    • 需要创建多个类(Builder、Director、Product等)
    • 对于简单对象,可能显得过于复杂
  2. 性能开销
    • 相比直接创建对象,有额外的对象创建和方法调用开销。这其实是设计模式的通病,灵活性的代价
  3. 灵活性受限
    • 产品必须有共同的接口,限制了产品类型的多样性。当产品差异性很大时,不推荐使用

6. 源码分析-JDK中的StringBuilder实现分析

主要关注append方法
StringBuilder源码简化分析:

publicfinalclassStringBuilderextendsAbstractStringBuilder{// 1. 存储产品(字符串)的字符数组// char[] value; // 继承自AbstractStringBuilderpublicStringBuilder(){super(16);// 初始容量}publicStringBuilder(intcapacity){super(capacity);}publicStringBuilder(Stringstr){super(str.length()+16);append(str);// 初始内容}// 2. 建造者方法 - 添加部件@OverridepublicStringBuilderappend(Stringstr){super.append(str);returnthis;// 关键:返回this实现链式调用}@OverridepublicStringBuilderappend(charc){super.append(c);returnthis;}@OverridepublicStringBuilderappend(inti){super.append(i);returnthis;}// 3. 获取最终产品@OverridepublicStringtoString(){// 创建String对象,使用当前的字符数组returnnewString(value,0,count);}}}

AbstractStringBuilder中的append:

abstractsealedclassAbstractStringBuilderimplementsAppendable,CharSequencepermitsStringBuilder,StringBuffer{publicAbstractStringBuilderappend(Stringstr){if(str==null){returnappendNull();}intlen=str.length();ensureCapacityInternal(count+len);putStringAt(count,str);count+=len;returnthis;}}

测试:

publicclassStringTest{staticvoidmain(String[]args){// 典型的建造者模式使用方式Stringresult=newStringBuilder().append("Hello")// 构建第一部分.append(" ")// 构建第二部分.append("World")// 构建第三部分.append("!")// 构建第四部分.reverse()// 对构建结果进行操作.toString();// 获取最终产品System.out.println(result);// 输出: !dlroW olleH}}

可以看到StringBuilder中的建造者模式特点:

  1. 内聚的建造者: StringBuilder同时承担了建造者和指挥者的职责
  2. 链式调用: 每个构建方法返回this,支持流畅接口(Fluent Interface)。这个在实际工作中常用Lombok的 @Builder注解
  3. 延迟创建: 只有在调用toString()时才创建最终的String对象

7. vs抽象工厂模式

关键区别总结:

  • 建造者模式: 关注如何构建一个复杂对象,构建过程是重点。粒度更细,可以理解为车间维度
  • 抽象工厂模式: 关注创建什么产品,产品家族是重点。粒度更粗,可以理解为工厂维度

实际选择经验建议:

  • 当需要创建的对象结构复杂、构建步骤多时,使用建造者模式
  • 当需要创建一系列相关对象时,使用抽象工厂模式
  • 在某些复杂场景下,两种模式可以结合使用,一个粗粒度,一个细粒度

参考:

  • 韩顺平 Java设计模式
  • 张维鹏 Java设计模式之创建型:建造者模式)
  • 设计模式实战——开发中经常涉及到的建造者模式
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/11 2:33:33

MapReduce 数据本地化优化策略

MapReduce 数据本地化优化策略:让计算像邻居串门一样高效关键词:MapReduce、数据本地化、任务调度、HDFS、性能优化、网络开销、分布式计算摘要:在大数据处理中,“让计算靠近数据”是提升效率的关键法则。本文以MapReduce为核心&a…

作者头像 李华
网站建设 2026/10/11 16:22:23

无需编程基础!手把手教你运行DDColor黑白上色模型

无需编程基础!手把手教你运行DDColor黑白上色模型 在泛黄的老照片里,祖辈的面容模糊而沉默;在尘封的家庭相册中,那些黑白影像承载着记忆,却少了生活的温度。我们渴望看见那个年代真实的色彩——阳光下的红砖墙、母亲衣…

作者头像 李华
网站建设 2026/10/11 3:52:19

清华镜像同步上线DDColor模型,下载速度提升300%

清华镜像同步上线DDColor模型,下载速度提升300% 在家庭相册里泛黄的黑白照片前驻足,几乎每个人都曾有过这样的瞬间——那些模糊的脸庞、褪色的衣裳,承载着一段段无法重来的时光。如今,AI正让这些记忆“重新着色”。随着深度学习技…

作者头像 李华
网站建设 2026/10/11 3:20:36

苹果App Store提交指南:将DDColor封装为iOS应用

苹果App Store提交指南:将DDColor封装为iOS应用 在智能手机成为家庭影像主要载体的今天,无数用户手中仍保存着泛黄褪色的老照片——祖辈的肖像、老屋的门庭、旧日街景。这些黑白图像承载着记忆,却因色彩缺失而显得遥远。如果能让AI“读懂”画…

作者头像 李华
网站建设 2026/10/5 12:56:17

零基础玩转Emuelec:系统安装通俗解释

零基础也能玩转Emuelec:从装系统到畅玩经典游戏的完整指南 你是否还记得小时候在红白机上通关《超级马里奥》的激动?或是守着PS1搓《最终幻想7》的深夜?如今,一块小小的开发板,就能让你把这些回忆重新搬回家中的电视大…

作者头像 李华