1. 1. 问题:
  1. 从零开始学设计模式(五):建造者模式(Builder Pattern) - 墨天轮

定义:

在现实世界中的很多东西都是由很多组成部分构成的,比如房子它由砖头、水泥、石灰、钢筋等组成,即一个个简单的组成部分构成了一个复杂的房子。同样在软件系统中也存在很多复杂对象,而复杂对象的一些属性就相当于盖房子的材料,创建对象的过程就相当于盖房子的过程。由于组合部件的过程很复杂,因此,这些部件的组合过程往往被“外部化”到一个称作建造者的对象里,然后建造者返还一个已经建造完毕的完整产品对象,而用户无须关心该对象所包含的属性以及它们的组装方式,这就是建造者模式的模式动机。

所以建造者模式的定义就是:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。生成器模式利用一个导演者对象和具体建造者对象一个一个地建造出所有的零件,从而建造出完整的对象。

组成部分:

通过上面对于建造者模式的介绍,可以发现建造者模式应该包含四个部分:

Builder:抽象建造者,定义创建一个Product对象所需要的各个部件的操作。

ConcreteBuilder:具体建造者,实现各个部件的创建,并负责组装Product对象的各个部件,同时还提供一个让用户获取组装完成后的产品对象的方法。

Director:指导者,主要用来使用Builder接口,以一个统一的过程来构建所需要的Product对象。

​ Product:产品,表示被建造者构建的复杂对象,包含多个部件。

优点:

1、使用建造者模式可以使客户端不必知道产品内部组成的细节。

2、具体的建造者类之间是相互独立的,对系统的扩展非常有利,有利于系统的解耦。

3、由于具体的建造者是独立的,因此可以对建造过程逐步细化,而不对其他的模块产生任何影响。

缺点:

1、产品的组成部分必须相同,这限制了其使用范围。

2、如果产品的内部变化复杂,如果产品内部发生变化,则建造者也要同步修改,后期维护成本较大。

应用场景:

建造者模式主要适用于以下应用场景:

1、相同的方法,不同的执行顺序,产生不同的结果。

​ 2、多个部件或零件,都可以装配到一个对象中,但是产生的结果又不相同。

3、产品类非常复杂,或者产品类中不同的调用顺序产生不同的作用。

​ 4、初始化一个对象特别复杂,参数多,而且很多参数都具有默认值。

问题:

一、为什么说****不同的执行顺序,产生不同的结果:

  1. 方法之间有依赖关系 - 某些操作需要在其他操作之后执行
  2. 构建过程有状态 - 每个方法都改变构建器内部状态
  3. 最终结果依赖于整个构建历史 - 不仅仅是调用了哪些方法,还包括调用的顺序
  4. 支持灵活的配置组合 - 通过调整顺序实现不同的产品变体

这也是建造者模式比简单setter方法更强大的地方:它不仅记录”设置了什么”,还隐式记录了”设置的顺序和上下文”,从而能够创建更复杂、更有结构的产品对象。

二、常见的建造者模式

  1. StringBuilder
1
2
3
4
5
6
String query = new StringBuilder()
.append("SELECT * FROM users")
.append(" WHERE age > ")
.append(18)
.append(" ORDER BY name")
.toString();
  1. Stream流
1
2
3
4
5
String result = Stream.of("Java", "Python", "Go", "Rust")
.filter(s -> s.length() > 2) // 过滤
.map(String::toUpperCase) // 转换
.sorted() // 排序
.collect(Collectors.joining(", "));
  1. mockito框架
1
2
3
4
// 参数匹配器建造者风格
when(mockService.findUsers(argThat(
criteria -> criteria.getAge() > 18 && criteria.isActive())))
.thenReturn(userList);