从建造者模式的定义上来看,使用多个简单的对象一步一步构建成一个复杂的对象。主要是在构建一个复杂对象时,将构建和表示分离。具体在什么场景使用,以及如何进行分离,比概念理解更加重要。
建造者模式,主要解决在创建一个复杂对象时,子对象不变,而组成方式不断变化的场景。
举个例子,假设我们有一个汽车类,该类具有多个复杂的属性,例如引擎、底盘、轮胎等。需要创建不同类型的汽车,跑车、轿车和SUV。构建汽车、轿车、SUV会有多种组合。借助建造者模式,我们可以实现这部分组合解耦。首先看下建造者模式的UML图是什么样的?
从UML图中,可以看出,Build可以实现横向扩展,即需要增加子对象组合时,只需要扩展Build即可。
下面,就从代码上实现一个建造者模式
// 管理者
var Director = function (builder) {
this.builder = builder;
};
Director.prototype.constructor = function (engine, chassis, tyres) {
this.builder.buildEngine(engine);
this.builder.buildChassis(chassis);
this.builder.buildTyres(tyres);
this.builder.build()
}
// 抽象构建者
var AbstractBuilder = function () {};
AbstractBuilder.prototype.setEngine = function (engine) {
throw new Error("子类必须实现此方法");
};
AbstractBuilder.prototype.setChassis = function (chassis) {
throw new Error("子类必须实现此方法");
};
AbstractBuilder.prototype.setTyres = function (tyres) {
throw new Error("子类必须实现此方法");
};
// 实际构建者
var Builder = function () {
this.car = new Car()
};
Builder.prototype = Object.create(AbstractBuilder.prototype);
Builder.prototype.constructor = Builder;
Builder.prototype.buildEngine = function (engine) {
this.car.engine = engine
};
Builder.prototype.buildChassis = function (chassis) {
this.car.chassis = chassis
};
Builder.prototype.buildTyres = function (tyres) {
this.car.tyres = tyres
};
Builder.prototype.build = function(){
console.log("构建汽车")
console.log("引擎",this.car.engine)
console.log("底盘",this.car.chassis)
console.log("轮胎",this.car.tyres)
return this.car;
}
var Car = function () {}
Car.prototype.engine = function (engine) {
this.engine = engine
}
Car.prototype.chassis = function (chassis) {
this.chassis = chassis
}
Car.prototype.tyres = function (tyres) {
this.tyres = tyres
}
let builder = new Builder;
let director = new Director(builder)
let suv = director.constructor("v8_engine", "chassis_","tyres_")
// 构建汽车
// index.html:101 引擎 v8_engine
// index.html:102 底盘 chassis_
// index.html:103 轮胎 tyres_
这里可以采用一种链式调用的方式,使得组合更加的灵活。
// 实际构建者
var Builder = function () {
this.car = new Car()
};
Builder.prototype = Object.create(AbstractBuilder.prototype);
Builder.prototype.constructor = Builder;
Builder.prototype.buildEngine = function (engine) {
this.car.engine = engine
return this
};
Builder.prototype.buildChassis = function (chassis) {
this.car.chassis = chassis
return this
};
Builder.prototype.buildTyres = function (tyres) {
this.car.tyres = tyres
return this
};
Director.prototype.constructor = function (engine, chassis, tyres) {
this.builder.buildEngine(engine).buildChassis(chassis).buildTyres(tyres).build()
}
这不是和工厂模式差不多嘛?那他们有什么区别?
-
创建方式:
- 工厂模式:通过创建一个单独的类(工厂类)来负责创建其他类的实例,这个工厂类通常使用一个简单的方法来返回一个适当类型的对象。
- 建造者模式:通过创建一个包含多个步骤或部件的复杂对象,并将这些步骤封装在一个单独的类(建造者类)中。建造者类通过调用其他对象的各种方法来逐步构建最终的对象。
-
关注点:
- 工厂模式:关注于产品的创建,通常只关心最终创建的对象类型,而不关心对象的组成部分或创建过程。
- 建造者模式:关注于产品的组成部分和创建过程,更注重细节和灵活性。建造者模式允许你在构建过程中逐步添加或删除部件,而无需改变其他部分的代码。
-
灵活性:
- 工厂模式:在需要创建多种类型对象的情况下,工厂模式可以提供一种简单且一致的方式来创建对象。但是,如果对象的创建过程需要大量自定义或复杂的步骤,工厂模式可能会变得过于复杂。
- 建造者模式:提供更大的灵活性,可以方便地修改和扩展对象的创建过程,以满足特定的需求。然而,由于建造者模式需要显式地调用每个步骤,因此在创建简单对象时可能会显得过于复杂。
因此,在创建对象的时候,有很多参数需要配置,组合场景还多的时候,可以采用建造者模式,便于扩展。