工厂模式(Factory Pattern)
我们试想一下,我们想创建一个复杂的对象,创建前需要做一二三四五六步,并且在业务中需要频繁进行对象创建。那么,选工厂模式就对了。一个工厂能提供一个创建对象的公共接口,我们可以在其中指定我们希望被创建的工厂对象的类型。
我们来看下代码:
function createVehicle(type) {
let context;
switch(type) {
case 'dog':
return new Dog(context);
case 'cat':
return new Cat(context);
case 'duck':
return new Duck(context);
}
}
复制代码
适用场景
- 当我们的对象或者组件设置涉及到高程度级别的复杂度时。
- 当我们需要根据我们所在的环境方便的生成不同对象的实体时。
- 当我们在许多共享同一个属性的许多小型对象或组件上工作时。
- 当带有其它仅仅需要满足一种API约定(又名鸭式类型)的对象的组合对象工作时.这对于解耦来说是有用的。
不适用场景
- 对象创建过程比较简单,过度的抽象不利于后期的维护迭代
抽象工厂模式(Abstract Factory Pattern)
可以简单理解为工厂的工厂。它的目标是以一个通用的目标将一组独立的工厂进行封装,它将一堆对象的实现细节从它们的一般用例中分离。
简单来说,就是工厂模式生产过程中的规格具有一些相似性,我们在制造前先把规格定义好,后续工厂实际加工过程中,只需要按照规格进行实施即可。
我们来看下代码:
function AbstractVehicleFactory() {
const _interface = {}
return {
getIns(key, context) {
const fn = _interface[key]
return fn(context)
},
register(key, fn) {
_interface[key] = fn;
return AbstractVehicleFactory
}
}
}
复制代码
单例模式(Singleton Pattern)
这应该是我们最熟悉的模式之一了,单例模式也称为单体模式,规定一个类只有一个实例,并且提供可全局访问点。比如操作系统的回收站,自始至终只有一个,如果出现两个,就会出现错乱。 我们来看下代码实现:
let Singleton = function(name){
this.name = name;
this.instance = null;
}
Singleton.prototype.getName = function(){
console.log(this.name);
}
Singleton.getInstance = function(name){
if(this.instance){
return this.instance;
}
return this.instance = new Singleton(name);
}
let winner = Singleton.getInstance("winner"); //winner
console.log(winner.getName());
let sunner = Singleton.getInstance("sunner"); //winner
console.log(sunner.getName())
复制代码
上面代码中我们是通过一个变量 instance 的值来进行判断是否已存在实例,如果存在就直接返回 this.instance,如果不存在,就新建实例并赋值给 instance。
我们不管调用多少次,实例对象只有一个。
建造者模式(Builder Pattern)
建造者模式使你能够分步骤创建复杂对象,该模式允许你使用相同的创建代码生成不同类型和形式的对象。
使用Builder的最常见的作用是简化创建复杂对象的客户端代码。客户端可以指导建造者创建,而不需要知道实际工作是如何完成的。
我们来看下代码实现:
function Builder() {
this.ins = null;
this.step1 = function() {
this.ins = new Ins();
};
this.step2 = function() {
this.ins.init();
};
this.get = function() {
return this.ins;
};
}
复制代码
建造者模式主要用于“分布构建一个复杂的对象”,它很容易进行扩展。如果有新的需求,通过实现一个新的建造者类就可以完成,并且建造者模式解耦了对象本身与构建过程,使得我们不用关心具体的建造过程。
原型模式(Prototype Pattern)
如Java这类语言,是通过类继承的,而Javascript的继承模式是原型,所以,我们实现远行继承可以基于原生能力。这一模式不仅仅是实现继承的一种简单方式,它顺便还能够带来一点性能上的提升:当定义对象的一个方法时,它们都是使用引用创建的(因此所有的子对象都指向同一个函数),而不是创建属于它们的单独的拷贝。
我们来看下代码实现:
var myCar = {
name: "myCar",
drive: function () {
// TODO
},
panic: function () {
// TODO
}
};
var yourCar = Object.create(myCar);
console.log(yourCar.name);