设计模式的核心是封装与隔离思想,工厂模式隔离了类与创建者,封装了类创建的逻辑,而本篇的主角建造者模式,封装和隔离的对象都是一样的,但它为什么又能从中脱颖而出喃?那就容我徐徐道来吧
业务场景
女朋友生日快到了,你为了浪漫(主要是为了省钱), 选择自己在家做蛋糕
class Cake {
public sugar: number;
public flour: number;
public water: number;
setSugar(sugar) { this.sugar = sugar }
setFlour(flour) { this.flour = flour }
setWater(water) { this.water = water }
runBake(minute) {
console.log(`烘烤${minute}分钟~~~`);
}
}
let cake = new Cake()
cake.setSugar(9999)
cake.runBake(80)
你由于从来没有做过蛋糕,也不知道做蛋糕加配料的顺序,在你的尝试了几次,全都无功而返,而且做的又黑又丑,你都怀疑那是不是生化武器,这显然不行啦!!!
所以你只有被迫求助甜品店厨师啦,你只需要告诉甜品店厨师你要的口味和大小就可以了,蛋糕的制作过程由甜品店厨师去完成
class Cake {
public sugar: number;
public flour: number;
public water: number;
setSugar(sugar) { this.sugar = sugar }
setFlour(flour) { this.flour = flour }
setWater(water) { this.water = water }
runBake(minute) {
console.log(`烘烤${minute}分钟~~~`);
}
}
class Desserter {
public cake: Cake
constructor() {
this.cake = new Cake()
}
build() {
this.cake.setFlour(100)
this.cake.setWater(20)
this.cake.setSugar(5)
this.cake.runBake(50)
return this.cake
}
}
// 甜品店厨师
let desserter = new Desserter()
let cake = desserter.build()
你终于拿到了心心念念的蛋糕了,虽然付出了一点点金钱,但是能让女朋友开心,这是很值得的
但是你不止她一个女朋友呀,其他女朋友也是近期过生日,你又找到甜品店厨师,让他帮你多做几个蛋糕,但是甜品店厨师不同意了,他每天的工作时间是有限的,怎么可以做那么多喃。然后甜品店厨师提出一个主意,他虽然没时间做,但是不代表他的徒弟没时间呀,他可以指挥他的徒弟们去做,你想了想,反正你又不吃,所以就欣然同意了
class Cake {
public sugar: number;
public flour: number;
public water: number;
setSugar(sugar) { this.sugar = sugar }
setFlour(flour) { this.flour = flour }
setWater(water) { this.water = water }
runBake(minute) {
console.log(`烘烤${minute}分钟~~~`);
}
}
interface PupilInterface {
creates(): Cake;
setBatching(): void
setBake(): void
}
class Pupil1 implements PupilInterface {
public cake: Cake
constructor() {
this.cake = new Cake()
}
setBatching() {
this.cake.setFlour(100)
this.cake.setWater(20)
this.cake.setSugar(5)
}
setBake() {
console.log("制做8分熟蛋糕~~");
this.cake.runBake(50)
}
creates() {
return this.cake
}
}
class Pupil2 implements PupilInterface {
public cake: Cake
constructor() {
this.cake = new Cake()
}
setBatching() {
this.cake.setFlour(100)
this.cake.setWater(20)
this.cake.setSugar(5)
}
setBake() {
console.log("制做5分熟蛋糕~~");
this.cake.runBake(20)
}
creates() {
return this.cake
}
}
class Desserter {
public pupilList: Array<PupilInterface>
constructor(pupilList) {
this.pupilList = pupilList
}
build() {
let cakeList: Array<Cake> = []
this.pupilList.forEach((pupil) => {
pupil.setBatching()
pupil.setBake()
let cake = pupil.creates()
cakeList.push(cake)
})
return cakeList
}
}
// 徒弟1
let pupil1 = new Pupil1()
// 徒弟2
let pupil2 = new Pupil2()
// 甜品店厨师
let desserter = new Desserter([
pupil1, pupil2
])
let cakes = desserter.build()
这下就皆大欢喜了,而且甜品店的不同徒弟也可以做出不同的蛋糕,不得不说,你是一个大渣男
JS实现建造者模式
function Cake() {
this.setSugar = function (sugar) {
this.sugar = sugar
}
this.setFlour = function (flour) {
this.flour = flour
}
}
function build() {
let cake = Cake()
cake.setSugar(10)
cake.setFlour(50)
return cake
}
let cake = build()
JS通过构造函数和闭包都可以实现建造者模式,而且比TS更简单方便
建造者模式
对照着渣男例子,来分析建造者模式
定义
将一个复杂类的构建对象的过程与对象的使用分离,使得同样的构建过程可以创建不同的对象
- 构建对象的过程与对象的使用分离(蛋糕的制作过程和蛋糕的使用并不是渣男一个人完成的)
- 同样的构建过程可以创建不同的对象(多个徒弟可以制作多种类型的蛋糕)
是不是一下就把官方定义读懂了喃?
角色
在编码实现的过程中,所需要的结构
| 角色 | 对应例子中的角色 | 作用 | 存在性 |
|---|---|---|---|
| 产品(Product) | 蛋糕(Cake) | 要被创建的产品 | 必须有 |
| 建造者接口(Builder) | 学徒技能(PupilInterface) | 要被建造者所实现的接口,规范学徒技能 | 可有可无 |
| 建造者(ConcreteBuilder) | 学徒(Pupil1、Pupil2) | 根据不同业务,建造不同类型的产品 | 必须有 |
| 调用者(Director) | 厨师(Desserter) | 调用建造者来完成任务 | 可有可无 |
在第一次你找厨师直接做蛋糕的时候,这也是建造者模式,并且这种还是我们最常用的,我极力推荐直接找厨师的方式!!!
你可能会疑问, 厨师并不能做其他蛋糕呀,这。。。。。加个方法不就可以了吗?
我们不必按照规则来约束自己的代码,最简单的才是最适合的,建造者接口和调用者只有在大型项目中才会遇见
使用场景
- 一个类实例过程很复杂,属性和方法特别多(蛋糕的制作过程是十分讲究的,配料、火候、顺序都有要求)
- 通过构建过程创建不同的对象(厨师可以做许多分类的蛋糕)
优缺点
优点
- 在建造对象时,用户不需要关心太多的逻辑(渣男也不用关心蛋糕怎么做)
- 建造过程和使用过程分离,可以建造不同类型的对象(各种类型蛋糕都可以制作)
缺点
- 代码量大,会新增建造类(渣男自己做蛋糕肯定是最快的方式,还不用钱)
- 产品类部发生改变,建造类也要跟着修改(如果哪天没有糖了,学徒和厨师就做不了蛋糕了)
建造者模式和工厂模式的区别
回到最初说的问题,建造者模式和工厂模式封装隔离的目标是一样的,为什么还会分为两个模式喃?
- 工厂模式注重创建对象的结果,而建造者模式注重的是创建过程
- 工厂模式适合不复杂类的创建,而对于复杂类的创建还得考建造者模式
- 工厂模式是根据传入参数的不同生成不同的对象,而建造者模式根据方法执行的不同生成不同的对象
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 20 天,点击查看活动详情