白山市网站建设_网站建设公司_漏洞修复_seo优化
2026/1/1 3:13:08 网站建设 项目流程

文章目录

  • 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设计模式之创建型:建造者模式)
  • 设计模式实战——开发中经常涉及到的建造者模式

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询