参考文章:
java设计模式之建造者模式
一、什么是建造者模式
建造者模式:是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
工厂类模式提供的是创建单个类的模式,而建造者模式则是将各种产品集中起来进行管理,用来创建复合对象,所谓复合对象就是指某个类具有不同的属性。
具体表现为4个角色
产品(Product):建造的产物
导演(Director):指挥建造的过程,不涉及建造的细节
建造者(Builder):抽象建造过程,规定产品哪些部分需要创建
具体建造者(ConceteBuilder):实现Builder,实现产品各个部分的建造,并提供产品
使用场景:
需要生成的对象有复杂的内部结构,且各部分都会根据需求发生组装变化
缺点:
1、当产品内部非常复杂,需要用大量的具体建造者,导致系统庞大
2、产品要有共同点,范围受限制
下面举个例子:肯德基点餐环节,角色对应分别如下
Product:一餐食物(Meal)
Director:前台销售员(Seller)
Builder:抽象建造者(Builder)
ConceteBuilder:厨师(Cook)
首先实现一些食物
// Food 食物抽象类
class Food {
constructor() {
this.name = null;
this.price = null;
}
}
// 汉堡
class Burger extends Food {
constructor() {
super();
this.name = '汉堡';
this.price = 16;
}
}
// 鸡翅
class ChickenWing extends Food {
constructor() {
super();
this.name = '鸡翅';
this.price = 12;
}
}
// 可乐
class Coke extends Food {
constructor() {
super();
this.name = '可乐';
this.price = 6;
}
}
产品Product
一桌餐饭可以有任意数量的任意组合
// Product
class Meal {
constructor() {
this.foods = [];
}
addFood(item) {
this.foods.push(item);
}
showPrice() {
var i = this.foods.length,
price = 0;
while(i--) {
price += this.foods[i].price;
}
return price;
}
}
抽象建造类Builder
规范各部分的建造
// Builder
class Builder {
cookBurger() {}
cookWing() {}
cookCoke() {}
finishCook() {}
}
具体建造类
厨师负责各个食物的烹饪,并添加到meal里
// ConceteBuilder
class Cook extends Builder {
constructor() {
super();
this.meal = new Meal();
}
cookBurger(number) {
for (var i = 0; i < number; i++) {
this.meal.addFood(new Burger());
}
}
cookWing(number) {
for (var i = 0; i < number; i++) {
this.meal.addFood(new ChickenWing());
}
}
cookCoke(number) {
for (var i = 0; i < number; i++) {
this.meal.addFood(new Coke());
}
}
finishCook() {
return this.meal;
}
}
导演Director
负责通知厨房需要烹饪啥啥啥。
// Director
class Seller {
constructor() {
this.builder = null;
}
bindCook(builder) {
this.builder = builder;
}
placeOrder(burgerAmount, wingAmount, cokeAmount) {
this.builder.cookBurger(burgerAmount);
this.builder.cookWing(wingAmount);
this.builder.cookCoke(cokeAmount);
var meal = this.builder.finishCook();
console.log('总价:' + meal.showPrice());
return meal;
}
}
最后模拟一次下单场景
var seller = new Seller();
var cook = new Cook();
seller.bindCook(cook);
seller.placeOrder(1, 2, 3); // 58
总结:
易于解耦
将产品本身与产品创建过程进行解耦,可以使用相同的创建过程来得到不同的产品。也就说细节依赖抽象。
易于精确控制对象的创建
将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰
易于拓展
增加新的具体建造者无需修改原有类库的代码,易于拓展,符合“开闭原则“。