2022-11-01 22:25:35 +08:00
|
|
|
|
### 简述
|
|
|
|
|
|
|
|
|
|
Builder 模式,中文翻译为建造者模式或者构建者模式,也有人叫它生成器模式。
|
|
|
|
|
|
|
|
|
|
### 示例
|
|
|
|
|
|
|
|
|
|
假设有这样一道设计面试题:我们需要定义一个资源池配置类 ResourcePoolConfig。这里的资源池,你可以简单理解为线程池、连接池、对象池等。在这个资源池配置类中,有以下几个成员变量,也就是可配置项。现在,请你编写代码实现这个 ResourcePoolConfig 类。
|
|
|
|
|
|
|
|
|
|
| 成员变量 | 解释 | 是否必填? | 默认值 |
|
|
|
|
|
| -------- | ---------------- | ---------- | ------ |
|
|
|
|
|
| name | 资源名称 | 是 | 无 |
|
|
|
|
|
| maxTotal | 最大总资源数量 | 否 | 8 |
|
|
|
|
|
| maxIdle | 最大空闲资源数量 | 否 | 8 |
|
|
|
|
|
| minIdle | 最小空闲资源数量 | 否 | 0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 总结
|
|
|
|
|
|
|
|
|
|
工厂模式和建造者模式的区别:工厂模式是用来创建不同但是相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定创建哪种类型的对象。建造者模式是用来创建一种类型的复杂对象,通过设置不同的可选参数,“定制化”地创建不同的对象。
|
|
|
|
|
|
|
|
|
|
如果一个类中有很多属性,为了避免构造函数的参数列表过长,影响代码的可读性和易用性,我们可以通过构造函数配合 set() 方法来解决。但是,如果存在下面情况中的任意一种,我们就要考虑使用建造者模式了。
|
|
|
|
|
|
|
|
|
|
- **依赖关系(Dependencies)**
|
|
|
|
|
|
|
|
|
|
我们把类的必填属性放到构造函数中,强制创建对象的时候就设置。如果必填的属性有很多,把这些必填属性都放到构造函数中设置,那构造函数就又会出现参数列表很长的问题。如果我们把必填属性通过 set() 方法设置,那校验这些必填属性是否已经填写的逻辑就无处安放了。
|
|
|
|
|
|
|
|
|
|
- **合法校验(Preconditions)**
|
|
|
|
|
|
|
|
|
|
如果类的属性之间有一定的依赖关系或者约束条件,我们继续使用构造函数配合 set() 方法的设计思路,那这些依赖关系或约束条件的校验逻辑就无处安放了。
|
|
|
|
|
|
|
|
|
|
- **不可变(Immutable)**
|
|
|
|
|
|
|
|
|
|
如果我们希望创建不可变对象,也就是说,对象在创建好之后,就不能再修改内部的属性值,要实现这个功能,我们就不能在类中暴露 set() 方法。构造函数配合 set() 方法来设置属性值的方式就不适用了。
|
|
|
|
|
|
|
|
|
|
###
|
|
|
|
|
|