文章初衷
设计模式其实旨在解决语言本身存在的缺陷,
目前javaScript一些新的语法特性已经集成了一些设计模式的实现,
大家在写代码的时候,没必要为了用设计模式而去用设计模式,
那么我这边为什么还写设计模式的文章呢,
一方面是自己的一个整理,然后记录出来,结合自己的理解,
一方面就是虽然语言特性本身已经实现这些模式,有了自己的语法,
但是我们何尝不能去了解一下它是通过什么样的思路去实现了
在我看来设计模式更多的是让我对于思考问题,有了一些更好的思路和想法
文章实现更多的表现为用一些简单的案例,帮助大家去理解这样的一种思路,
会存在故意把设计模式的实现往简单的案例靠拢,
大家在真实项目中不要刻意去用设计模式实现相同的代码
设计模式在平时的一些代码中都会有所体现,大家也许经常用到,
耐心看文章,也许你会发现自己平时的代码就不断在设计模式中体现
JavaScript设计模式系列
JavaScript设计模式系列,讲述大概20-30种设计模式在JavaScript中的运用
后面对应的篇幅会陆续更新,欢迎大家提出建议
这是设计模式系列第二篇,讲述建造者模式
注意
深入系列文章部分是有先后顺序的,按照目录结构顺序阅读效果最好。
勘误及提问
如果有疑问或者发现错误,可以在相应的 issues 进行提问或勘误。
如果喜欢或者有所启发,欢迎 star,对作者也是一种鼓励。
建造者模式
概念:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建
不同的表示。
不管扯淡的概念,上🌰,后面再反过头来理解这句话
// #建造者模式
// 抽象建造者
var Car = function (param) {
// 速度
this.speed = param && param.speed || '0';
// 重量
this.weight = param && param.weight || '0';
}
Car.prototype = {
// 获取速度
getSpeed: function () {
return this.speed;
},
// 获取重量
getWeight: function () {
return this.weight
}
}
// 轮胎部件类
var Tyre = function (type) {
var that = this;
// 构造器
// 构造函数中通过传入的type类型设置相对应的轮胎尺寸
(function (type,that) {
switch (type) {
case 'small':
that.tyre = '小号轮胎';
that.tyreIntro = '正在使用小号轮胎';
break;
case 'normal':
that.tyre = '中号轮胎';
that.tyreIntro = '正在使用中号轮胎';
break;
case 'big':
that.tyre = '大号轮胎';
that.tyreIntro = '正在使用大号轮胎';
break;
}
})(type,this);
}
Tyre.prototype = {
// 更换轮胎的方法
changeType: function (type) {
that.tyre = type;
that.tyreIntro = '正在使用'+type;
}
}
// 发动机部件类
var Engine = function (type) {
var that = this;
// 构造器
// 构造函数中通过传入的type类型设置相对应的发动机类型
(function (type,that) {
switch (type) {
case 'small':
that.engine = '小号发动机';
that.engineIntro = '正在使用小号发动机';
break;
case 'normal':
that.engine = '中号发动机';
that.engineIntro = '正在使用中号发动机';
break;
case 'big':
that.engine = '大号发动机';
that.engineIntro = '正在使用大号发动机';
break;
}
})(type,this);
}
Engine.prototype = {
// 更换发动机的方法
changeType: function (type) {
that.engine = type;
that.engineIntro = '正在使用'+type;
}
}
/**
* 指挥者,建造一个奔驰车的类
* @param {*轮胎类型 small normal big} tyre
* @param {*发动机类型 small normal big} engine
* @param {*车辆基本属性 param.speed:速度 param.weight: 重量} param
*/
var BenChi = function (tyre,engine,param) {
// 创建一个车辆缓存对象
var _car = new Car(param);
// 创建车辆的轮胎
_car.tyreInfo = new Tyre(tyre);
// 创建车辆的发动机
_car.engineInfo = new Engine(engine);
// 将创建的车辆对象返回
return _car;
}
// 具体建造者 实例化奔驰车类
var benchi1 = new BenChi('small','big',{speed: 200,weight: '200'});
console.log(benchi1.speed);// 200
console.log(benchi1.weight);// 200
console.log(benchi1.tyreInfo.tyre);// 小号轮胎
console.log(benchi1.tyreInfo.tyreIntro);// 正在使用小号轮胎
console.log(benchi1.engineInfo.engine);// 大号发动机
console.log(benchi1.engineInfo.engineIntro);// 正在使用大号发动机
// #建造者模式end复制代码
这段例子是这样的意思,首先我们要建造一个车,
那么车是一个比较复杂的东西,我们需要轮胎部件,发动机部件等等其他
复杂的部件,每个部件相对来说又是独立的个体,又是具备很多独立的行为
那么针对这种复杂的对象(例子中是一辆车),我们把它分成一个个部件,
然后通过一系类的组装,把这些部件都拼接在一起,组成一个复杂的对象,
这样的方式就是建造者模式,一步步构建一个复杂的对象,
用户只关心最后建造出来的车,不需要关心它具体的部件是如何实现的
建造者模式中存在的角色
这边介绍一下建造者模式中存在的角色,方便大家去理解
- 抽象建造者
- 指挥者
- 具体建造者
结合上面的案例,我们去把案例中的情况根据角色去划分一下,
这样更好的去理解建造者模式
首先Car就是抽象建造者,它具备一些车的基本属性还有方法,
它是抽象的,用户不需要知道它的存在,
那么Tyre(轮胎),Engine(发动机),分别就是车的具体部件(具体类),
创建的BenChi类,其实就是一个指挥者的角色,负责把对应的部件组装起来,
具体创建一个什么样子的车,就是指挥者这边决定的,
比如说这边还有一个空调部件,有些车没有的话,那么指挥者在创建的时候,
就不需要加入这个部件,所以对象的建造都是指挥者这边决定的
再下面就是具体建造者了,指挥者创建了一个奔驰车的类,
那么具体建造者,通过调用这个类去实现不同的车系,
比如奔驰车它有很多系列,通过传递不同的参数,就可以创建不同的系列
这就是一个完整的建造者案例,把复杂对象简单化,通过建造不同的部件类,
组成一个复杂的对象,不同的部件,在创建不同对象的时候,可以进行复用。
建造者模式的优点
在建造者模式中,客户端不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。
可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。
建造者模式的缺点
- 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此其使用范围受到一定的限制。
- 如果产品的内部变化复杂,可能会导致需要定义很多具体建造者类来实现这种变化,导致系统变得很庞大。
建造者模式的适用情况
需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
隔离复杂对象的创建和使用,并使得相同的创建过程可以创建
不同的产品。
工厂模式与建造者模式的比较
- 与抽象工厂模式相比,建造者模式返回一个组装好的完整产品,
而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族。
- 在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象,而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,
它侧重于一步步构造一个复杂对象,返回一个完整的对象。
- 如果将抽象工厂模式看成汽车配件生产工厂,生产一个产品族的产品,
那么建造者模式就是一个汽车组装工厂,通过对部件的组装可以返回一辆完整的汽车。
建造者模式的总结
建造者模式将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。建造者模式属于对象创建型模式。
建造者模式包含3个角色,抽象建造者创建对象的基本属性方法,
指挥者用来组装具体的部件,形成不同的对象,具体建造者负责实现指挥者创建的对象
最后我们再来理解建造者模式的概念就比较简单了:
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建
不同的表示。
注意
深入系列文章部分是有先后顺序的,按照目录结构顺序阅读效果最好。