javaScript设计模式-Factory(工厂)模式

Factory模式是另一种创建型模式,涉及创建对象的概念。其分类不同于其他模式的地方在于它不是显式地要求使用一个构造函数。而Factory可以提供一个通用的接口来创建对象,我们可以指定我们所希望创建的工厂对象的类型

下面这个示例构建在之前的代码片段之上,使用Constructor模式逻辑来定义汽车。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
function Car(options = {}) {
this.doors = options.doors || 4;
this.state = options.state || "brand new";
this.color = options.color || "silver";
}

//定义Truck构造函数
function Truck(options = {}) {
this.state = options.state || "used";
this.wheelSize = options.wheelSize || 'large';
this.color = options.color || 'blue';
}


function VehicleFactory() {}

VehicleFactory.prototype.vehicleClass = Car;

VehicleFactory.prototype.createVehicle = function(options) {
if(options.vehicleType === 'car') {
this.vehicleClass = Car;
} else {
this.vehicleClass = Truck;
}

return new this.vehicleClass(options);
};

var carFactory = new VehicleFactory();
var car = carFactory.createVehicle({
vehicleType: 'car',
color: 'yellow',
doors: 6,
})

console.log(car instanceof Car);
console.log(car);

在方法1中,我们修改了VehicleFactory实例来使用Truck类:

1
2
3
4
5
6
7
8
9
var movingTruck = carFactory.createVehicle({
vehicleType: 'truck',
state: 'like new',
color: 'red',
wheelSize: 'small'
})

console.log(movingTruck instanceof Truck);
console.log(movingTruck);

在方法2中,我们把VehicleFactory归入子类来创建一个构建Truck的工厂类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function TruckFactory() {}

TruckFactory.prototype = new VehicleFactory();
TruckFactory.prototype.vehicleClass = Truck;

var truckFactory = new TruckFactory();
var myBigTruck = truckFactory.createVehicle({
state: 'omg..so bad',
color: 'pink',
wheelSize: 'so big',
})

console.log(myBigTruck instanceof Truck);
console.log(myBigTruck)

何时使用Factory模式

Factory模式应用于如下场景是特别有用的:

  1. 当对象或组件设置涉及高复杂性时
  2. 当需要根据所在的不同环境轻松生成对象或组件时
  3. 当处理很多共享相同属性的小型对象或组件时
  4. 在编写只需要满足一个API契约(亦称鸭子类型)的其他对象的实例对象时

何时不应使用Factory模式

如果应用错误,这种模式会为应用程序带来大量不必要的复杂性。除非为创建对象提供一个接口是我们正在编写的库或框架的设计目标,否则建议坚持使用显示构造函数,以避免不必要的开销。

Abstract Factory(抽象工厂)

它用于封装一组具有共同目标的单个东厂。它能够将一组对象的实现细节从一般用法中分离出来。

应当使用抽象工厂模式的情况是:一个系统必须独立于它所创建的对象的生成方式,或它需要与多种对象类型一起工作。

既简单由容易理解的示例是车辆工厂,它定义了获取注册车辆类型的方法。抽象工厂可以命名为AbstractVehicleFactory。抽象工厂允许对象car或truck这样的车辆类型进行定义,具体工厂只需要实现履行车辆契约的类(如:Vehicle.prorotype.drive和Vehicle.prototype.breakDown)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
var AbstractVehicleFactory = (function() {

// 存储车辆类型
var types = {};

return {
getVehicle: function(type, customizations) {
var Vehicle = types[type];

return (Vehicle) ? new Vehicle(customizations) : null;
},

registerVehicle: function(type, Vehicle) {
var proto = Vehicle.prototype;
var v = new Vehicle();
// 只注册实现车辆契约的类
if(v.drive && !v.breakDown) {
types[type] = Vehicle;
}
return AbstractVehicleFactory;
}
}
})()

AbstractVehicleFactory.registerVehicle('car', Car);
AbstractVehicleFactory.registerVehicle('truck', Truck);

// 基于抽象车辆类型示例化一个新car对象
var car1 = AbstractVehicleFactory.getVehicle('car', {
color: 'lime green',
state: 'like new',
})

// 同理实例化一个新truck对象
var truck1 = AbstractVehicleFactory.getVehicle('truck', {
wheelSize: 'medium',
color: 'neon yellow',
})

console.log(car1);
console.log(truck1)