生成器模式
生成器模式是一种创建型设计模式,使你能够分步创建复杂对象。
使用场景:当你尝试构建一个拥有许多配置选项的对象时,该模式会特别有用。
生成器模式的主要角色如下:
- 生成器:接口生命再所有类型生成器中通用的产品构造步骤
- 具体生成器:提供构造过程的不同实现。具体生成器也可以构造不遵循通用接口的产品
- 产品:是最终生成的对象。由不同生成器构造的产品无需属于同一类层次构造或接口
- 指挥者<可选>:定义调用构造步骤的顺序,这样你就可以创建和服用特定的产品配置
- 客户端:必须将某个生成器对象与主管类关联,一般情况下,你只需要通过指挥者类构造函数的参数进行一次性关联即可
什么是复杂对象?:当一个类的构造函数接收很多个参数,且有些参数是可选的。那么当实列化这个类时就要传递很多类参数给构造函数,而且当有些属性有值,有些属性无值时,传递参数就会像下面这个情况:
typescript
new Computer("Intel i7", 16, "512GB SSD", "NVIDIA GTX 3060",
"Windows 11", true, false, true, "Wi-Fi 6", "Bluetooth 5.0",
null, null, ...);写法不仅难以阅读,还容易传错参数。
生成器模式的目的是实现分步创建对象,通过分布设置属性的方式为可选属性赋值。提高代码灵活性与可读性。如:
typescript
const computer = new ComputerBuilder()
.setCpu("Intel i7")
.setRam(16)
.setStorage("512GB SSD")
.setGpu("NVIDIA GTX 3060")
.build();实现过程
有一个产品类如下:
typescript
class Computer {
private cpu: string
private ram: string
private usbCount?: number
private keyboard?: string
private display?: string
constructor(builder: ComputerBuilder) {
//因为产品跟其对应的构造器的属性是一样的,所以直接拿构造器的属性覆盖产品属性
Object.assign(this, builder)
}
/**
* 获取可选参数<ram>的值
* @returns
*/
public getRam() {
return this.ram
}
/**
* 获取可选参数<cpu>的值
* @returns
*/
public getCpu() {
return this.cpu
}
/**
* 获取可选参数<usbCount>的值
* @returns
*/
public getUsbCount() {
return this.usbCount
}
/**
* 获取可选参数<usbCount>的值
* @returns
*/
public getKeyboard() {
return this.keyboard
}
/**
* 获取可选参数<dispaly>的值
* @returns
*/
public getDisplay() {
return this.display
}
}为这个产品设立一个构造器:构造器的最终目的是返回产品对象。代码如下:
typescript
class ComputerBuilder {
//构造器的属性特性需要与产品的属性特性保持一致,如产品的属性是可选的,那么构造器对应的属性也要是可选的
public cpu: string
public ram: string
public usbCount?: number
public keyboard?: string
public display?: string
constructor() {}
/**
* 为必选参数赋值
* @param cpu
* @param ram
*/
public Builder(cpu: string, ram: string) {
this.cpu = cpu
this.ram = ram
return this
}
/**
* 为可选属性<usbCount>单独赋值,并返回当前对象
* @param v
* @returns this
*/
public setUsbCount(v: number) {
this.usbCount = v
return this
}
/**
* 为可选属性<keyboard>单独赋值,并返回当前对象
* @param v
* @returns
*/
public setKeyboard(v: string) {
this.keyboard = v
return this
}
/**
* 为可选属性<display>单独赋值,并返回当前对象
* @param v
* @returns
*/
public setDispaly(v: string) {
this.display = v
return this
}
/**
* 执行构建,或者说完成构建
* @returns
*/
public build() {
return new Computer(this)
}
}使用构造器分步创建不同对象:
typescript
//创建一个计算机实例,只有必选参数的对象
const $instance = new ComputerBuilder.Builder('因特尔', '三星').build()
console.log('[ $instance ] >', $instance)
//创建一个计算机实例,有必选和一个可选参数的实例
const $instance2 = new ComputerBuilder.Builder('因特尔', '三星').setKeyboard('雷蛇').build()
console.log('[ $instance2 ] >', $instance2.getCpu(), $instance2.getKeyboard())代码更容易维护。