# 建造者模式
# 参考
# 定义
亦称,生成器模式、Builder模式。将一个复杂对象的构造与它的表示分离,能够使用相同的代码生成不同了类型的对象。它是将一个复杂的对象创建过程分解为一个个简单的步骤、对象,然后一步步构成。
# 应用场景
需要生成的对象有复杂的内部结构,获取、生成正确类型的对象步骤相对复杂、繁琐。
相同的方法,不同的执行顺序,会产生不同的结果,执行顺序需要能够灵活调整、扩展。
多个组件、属性都可以装配到同一个对象中,产生不同的对象。
如一家咖啡店能制作多种咖啡,每种咖啡的制作步骤、原料添加都有所不同。如果让客户(client)去负责咖啡的调制那这家店可以倒闭了,所以咖啡店都有专门的咖啡师(director)来负责咖啡的制作,客户点单即可。所有咖啡有基本的制作模板,比如加咖啡豆、加水、加奶等等,咖啡师根据不同咖啡的不同制作步骤、不同原料来制作一杯咖啡。
# 实现、应用思路
产品类(Product):最终生成的产品或期间用于组装产品的子部件。
抽象建造类(Builder):包含创建产品各个子部件的抽象方法的接口,通常有一个用于返回复杂产品的方法。
具体建造者类(Concrete Builder):实现抽象建造类接口,完成复杂产品的各个具体创建步骤。
指挥者、主管类(Director):定义按照特定顺序,调用构建者中的构造、装配方法,来完成复杂对象的创建。
# 优点
低耦合,对象构建与表示分离。
扩展性好,各个具体构建者的相互独立,构建步骤可自定义,有利于系统解耦。
客户端不必谁知道对象生成细节,就能生成复杂对象
# 缺点
需要新增多个类,有可能让系统变得更难理解,复杂度提高。
与产品耦合,如果产品的方法改了,建造者越要跟着改。
# 建造者模式和工厂模式的不同
两个模式乍看之下非常相似,因为都是用于生产对象的创建型设计模式,但两者的关注点有所不同。
建造者模式要知道对象的组成部分,更关注对象的创建步骤、组装,而工厂模式的关注点在于创建对象即可。
建造者模式适用于创建复杂、各有差异的对象,而工厂模式生产的是一样的对象。
# 代码实例
// 抽象产品
export abstract class Coffee {
abstract bean: number
abstract water: number
abstract milk: number
abstract price: number
}
// 具体产品,美式咖啡
class American extends Coffee {
bean = 0
water = 0
milk = 0
price = 10
}
// 具体产品,拿铁咖啡
class Latte extends Coffee {
bean = 0
water = 0
milk = 0
price = 20
}
// 抽象建造者
abstract class CoffeeBuilder {
abstract type: string
abstract coffee: Coffee
abstract addCoffeeBean(grams: number): void
abstract addWater(grams: number): void
abstract addMilk(grams: number): void
getCoffee() {
return this.coffee
}
}
// 具体建造者,美式建造者
class AmericanBuilder extends CoffeeBuilder {
type: string = 'AmericanCoffee'
coffee: Coffee
constructor() {
super()
this.coffee = new American()
}
addCoffeeBean() {
this.coffee.bean = 3
}
addWater() {
this.coffee.water = 3
}
addMilk() {
this.coffee.milk = 0
}
}
// 具体建造者,拿铁建造者
class LatteBuilder extends CoffeeBuilder {
type: string = 'LatteCoffee'
coffee: Coffee
constructor() {
super()
this.coffee = new Latte()
}
addCoffeeBean() {
this.coffee.bean = 2
}
addWater() {
this.coffee.water = 2
}
addMilk() {
this.coffee.milk = 2
}
}
// 主管类
class Director {
makeAmerican() {
const americanBuilder = new AmericanBuilder()
americanBuilder.addCoffeeBean()
americanBuilder.addWater()
americanBuilder.addMilk()
return americanBuilder.getCoffee()
}
makeLatte() {
const latteBuilder = new LatteBuilder()
latteBuilder.addCoffeeBean()
latteBuilder.addWater()
latteBuilder.addMilk()
return latteBuilder.getCoffee()
}
}
// 客户端
class Client {
constructor() {
const director = new Director()
const american = director.makeAmerican()
const latte = director.makeLatte()
console.log(american, latte)
}
}
new Client()