一、什么是建造者模式
1、定义
建造者模式属于创建型模式的一种,将一个复杂的对象分解成多个简单的对象来进行构建,将复杂的构建层与表示层分离,使得相同的构建过程可以创建不同的表示的模式便是建造者模式
优点:
- 对象本身与构建过程解耦。
- 建造者模式很容易进行扩展。如果有新的需求,通过实现一个新的建造者类就可以完成。
- 建造者模式的封装性很好。使用建造者模式可以有效的封装变化,在使用建造者模式的场景中,一般产品类和建造者类是比较稳定的,因此,将主要的业务逻辑封装在指导者类中对整体而言可以取得比较好的稳定性。
2、原理图
建造者模式的结构
| 角色 | 类别 | 说明 |
|---|---|---|
| Director | 接口或者抽象的类 | 统一指挥建造者去建造目标,不是必须的 |
| Builder | 接口或者抽象的类 | 给出一个抽象结论,以规范产品对象的各个组成成分的建造。这个接口规定要实现复杂对象的那些部分的创建,并不涉及具体的对象部件的创建。 |
| ConcreteBuilder | 具体的建造者 | 实现Builder接口,针对不同的商业逻辑,具体化复杂对象的各部分的创建。在构造过程完成后,提供产品的实例。 |
| product | 具体的类 | 具体的产品(即被建造的对象) |
解释说明
- 指挥者(Director)直接和客户(Client)进行需求沟通;
- 沟通后指挥者将客户创建产品的需求划分为各个部件的建造请求(Builder);
- 将各个部件的建造请求委派到具体的建造者(ConcreteBuilder);
- 各个具体建造者负责进行产品部件的构建;
- 最终构建成具体产品(Product)。
3、举例说明
1、软件开发
如果我们需要开发一个新的产品的话,那么首先需要产品经理(相当于指挥者(Director))和客户沟通,确定产品需求,技术主管就是抽象的Builder,分发给程序员(具体的构建者(ConcreteBuilder))任务。程序员去按照技术主管分发的任务去做
2、建房子
我们盖房子,一般就是先打地基,再盖框架(房子的形状,用砖头和混凝土),然后是粉刷。我们不想自己设计,直接去找了一个设计师,告诉他说我就要这样的房子,最后设计师给一张纸给工人,工人就开始造房子了,然后等房子造好再去验收即可,(至于你是如何建的过程我不关心,我只要结果)---这就是建造者模式
3、买电脑
电脑城老板(Diretor)和小明(Client)进行需求沟通(买来打游戏?学习?看片?)、了解需求后,电脑城老板将小明需要的主机划分为各个部件(Builder)的建造请求(CPU、主板blabla),然后指挥装机人员(ConcreteBuilder)去构建组件,将组件组装起来成小成需要的电脑(Product)。
电脑都是由主板、内存、cpu、显卡等组成,不同的人对电脑的配置需求不一样的「打游戏的对显卡要求高」,但是电脑构成部件是固定的,我们找电脑城的装机人员把电脑装起来这一过程就是建造模式,如何把这些东西组装起来给用户这就是建造者模式的作用
二、建造者模式要怎么用
1、应用场景
需要生成的对象具有复杂的内部结构;需要生成的对象内部属性本身相互依赖
2、 实例
产品类为一辆加工的空壳汽车、主要部件都一样(引擎,轮子,方向盘)和流程是不变的,变的是引擎,轮子,控制系统等等部件具体实现。
产品类
/**
* 产品类:car 目前需要构建一辆车。
*/
function car () {
this.name = '',
this.number = '',
this.wheel = '',
this.engine = ''
}
建造类
/*
* 建造者类,里面有专门负责各个部分的工人
*/
function carBuilder () {
this.nameBuilder = function () {
this.name = '很厉害的车'
},
this.numberBuilder = function () {
this.number = '88888888'
},
this.wheelBuilder = function () {
this.wheel = '高级橡胶做的轮子'
},
this.engineBuilder = function () {
this.engine = '很厉害的引擎'
},
this.getCar = function () {
var Car = new car()
Car.name = this.name;
Car.number= this.number;
Car.wheel = this.wheel;
Car.engine = this.engine;
return Car;
}
}
//在这里我们可以看到各个部分的工人以及他们的工作
指挥类
/**
* 指挥者类,指挥各个部分的工人工作
*/
function director () {
this.action = function (builder) {
builder.nameBuilder();
builder.numberBuilder();
builder.wheelBuilder();
builder.engineBuilder();
}
}
使用方法
/**
* 使用方法
*/
var builder = new carBuilder();
var director = new director();
director.action(builder);
var Car = builder.getCar();
console.log(Car);
最终客户通过getCar方法得到了这辆车,并且不需要知道其中得建造细节。
3、其他举例
// 创建框架的构造函数
function Frame(quality) {
this.name = 'frame';
this.quality = quality;
}
// 创建填充的构造函数
function Fill(quality) {
this.name = 'fill';
this.quality = quality;
}
// 创建包装的构造函数
function Pack(quality) {
this.name = 'pack';
this.quality = quality;
}
// 创建产品类,最终产品为他的实例
function Product() {
// 假设一件产品需要有 框架、填充、包装 三个属性
// 三个属性设置为私有,这样外部就不会不小心修改掉
var frame, fill, pack;
// 设定修改和获取方法
this.setFrame = function (val) {
frame = new Frame(val);
}
this.getFrame = function () {
return frame;
}
this.setFill = function (val) {
fill = new Fill(val);
}
this.getFill = function () {
return fill;
}
this.setPack = function (val) {
pack = new Pack(val);
}
this.getPack = function () {
return pack;
}
// 定义查看产品信息的方法
this.showInfo = function () {
console.log(`
框架:${frame.name} - ${frame.quality}
填充:${fill.name} - ${fill.quality}
包装:${pack.name} - ${pack.quality}
`);
}
}
// 建造者原型,封装建造方法,这里可以根据不同的需求,定制不同的建造者
function Builder() {
// 创建产品的实例
var product = new Product();
// 建造者创建产品的函数
this.buildFrame = function () {
product.setFrame(100);
}
this.buildFill = function () {
product.setFill(60);
}
this.buildPack = function () {
product.setPack(40);
}
this.exportProduct = function () {
return product;
}
}
// 指导者,控制规范建造的流程
function Director() {
// 实例化具体的建造者
var builder = new Builder();
// 指导者的开始建造命令
this.build = function () {
builder.buildFrame();
builder.buildFill();
builder.buildPack();
return builder.exportProduct();
}
}
// 使用阶段
// 创建一个指导者,规划生产流程
var director = new Director();
// 根据流程创建商品
var product = director.build();
// 查看生产产品详情
product.showInfo();
// 查看某一个属性
console.log(product.getFrame());