建造者模式,在JavaScript的设计模式中,能够用上的次数非常少。但是,它的优点确实非常的明星,就是能够构建不同的大类,使一个比较复杂的对象能够通过“建造”的方式构造出来。其中,构造的内容也是可以非常的丰富多彩。我们可以把建造者模式想象成一个产品(制作的东西,也就是我们需要的成品),一个中间层(一般来说都是抽象接口,也可以称作导演),一个或者多个建造者(可以有多个具体项)。也就是,我们需要清楚的知道,这个产品的形成过程,而不能够像之前的工厂模式一样,实现的过程隐藏得很深。
一、建造者模式四要素
1)产品类Product:一般是一个较为复杂的对象,也就是说创建对象的过程比较复杂,一般会有比较多的代码量。 2)抽象建造者类Builder: 将建造的具体过程交与它的子类来实现,这样更容易扩展。 3)建造者类ConcreteBuilder: 组建产品;返回组建好的产品。 4)指导类Director: 负责调用适当的建造者来组建产品,指导类一般不与产品类发生依赖关系,与指导类直接交互的是建造者类。
二、建造者模式的优缺点
- 优点:
1、降低代码耦合度。在建造者模式中,客户端不需要知道产品内部是如何实现的,我们只需得到产品的对象。并且使用导演者和建造者分离组装过程和组件具体构造过程。
2、优良扩展性。多个建造者相互独立,方便扩展。
3、符合开闭原则。
- 缺点
不适用于产品内部差异性大的情况,否则代码实现类会比较多,造成代码过于累赘复杂
三、建造者模式的实现
先简单的举一个构建房子的例子:
function HouseProduct() { //房子产品,我们要建一个房子,包括了卧室、大厅、厨房、书房
this.BedRoom = '';
this.Hall = '';
this.Kitchen = '';
this.studyRoom = '';
}
function Director() {// 这就是导演,只会指挥、布局,而不用知道具体细节
this.construct = function(houseBuilder) {
houseBuilder.build_BedRoom();
houseBuilder.build_Hall();
houseBuilder.build_Kitchen();
houseBuilder.build_studyRoom();
}
}
function houseBuilder() {//具体的建造者,我们在这里书写详细的建造过程
this.build_BedRoom= function() {
console.log('The bedroom has been built!');
}
this.build_Hall= function() {
console.log('The hall room has been built!');
}
this.build_Kitchen= function() {
console.log('The kitchen has been built!');
}
this.build_studyRoom= function() {
console.log('The studyroom has been built!');
}
this.getProduct = function() {
var house = new HouseProduct();
house.BedRoom = 'okay';
house.Hall = 'okay';
house.Kitchen = 'okay';
house.studyRoom = 'okay';
return house;
}
}
var houseBuilder = new houseBuilder;
var director = new Director;
director.construct(houseBuilder);
var goodhouse = houseBuilder.getProduct();
看到这里,想必都应该知道了,建造者模式就是将不同的构建内容统一到建造者中,然后通过一定的方式进行组装调用,最后在产品上呈现出来。
我们可以用es6来建造一下建造者模式。如下:
我们先将HouseProduct变成一个类
class HouseProduct {
constructor(name) {
console.log(`开始构建${name}房子`)
this.worker = ''
}
build(partName) {
console.log(`${partName}`)
this.worker = new worker(partName)
}
getResult() {
console.log('完成构建工作')
return this.worker
}
}
class worker {
constructor(material) {
console.log(`我建造了${material}`)
this.data = material
}
}
class Developer {
constructor() {
this.need = ['卧室', '厨房', '客厅', '书房']
console.log("这才是家")
}
construct() {
console.log("开始建造房子")
let workerOk=this.need.map(el=>{ //这里是因为need的都是差不多形式的,所以才用map
let builder = new HouseProduct('King')
builder.build(el)
return builder.getResult()
})
console.log("温馨的房子")
console.log(workerOk)
}
}
// 要求产品
let home = new Developer()
// 生成产品
home.construct()
其实,工厂模式已经满足大部分的场景。只是建造者模式适合更加复杂的场景,或者建造一个大的产品的时候可能用到。都有一定的优缺点。建议不熟悉建造者模式的朋友还是少用这个模式,毕竟我们产品多了以后自行拆解成几个工厂也是一样的哦。