前言:Factory 工厂模式涉及到对象的概念,但它不显式地要求使用一个构造函数,而是提供一个通用的接口来创建对象,我们可以指定所希望创建的工厂对象的类型。
Factory 工厂模式的用途 若是我们需要创建的对象比较复杂( 该对象强烈依赖于动态因素或应用程序配置 )便可以考虑使用 Factory 模式
Factory 工厂模式例子 假设我们有一个汽车工厂 VehicleFactory ,其可以生产两种类型的车 Car 和 Truck。下面我们使用 Factory 模式来实现 VehicleFactory 工厂,代码如下:
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 42 43 44 45 function Car (options ) { this .doors = options.doors || 4 ; this .state = options.state || 'brand new' ; this .color = options.color || 'silver' ; } 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);
若是我们想使用 VehicleFactory 工厂生产 Truck, 代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 // 生产 Truck var truck = carFactory.createVehicle({ vehicleType: "truck" , state : "like new" , color: "yellow" , doors: 8 }); // 测试汽车是由 VehicleFactory 原型 prototype 中的 Truck 创建的 // 输出 true console.log (truck instanceof Truck); // 输出 Truck 对象,Truck { state : 'like new', wheelSize: 'large', color: 'yellow' } console.log (truck);
我们也可以将 VehicleFactory 归入子类来构建一个 Truck 的工厂类,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 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 模式的场景
当对象或组件涉及高复杂性时
当需要根据所在的不同环境轻松生成对象的不同实例时
当处理很多共享相同属性的小型对象或组件时
在编写只需要一个 API 契约( 鸭子类型 )的其他对象的实例对象时,有利于解耦
Factory 模式的缺点
若是应用失当,该模式会给应用带来大量不必要的复杂性。
由于没有显式的对象实例化过程( 对象的实例化隐藏在了 Factory 模式的内部 ),单元测试时有可能会带来意想不到的问题
Abstract Factory 抽象工厂 抽象工厂模式是工厂模式的高级用法,它用于封装一组具有共同目标的单个工厂。它能够将一组对象的实现细节从一般用法中分离出来。
Abstract Factory 的使用场景举例 一个系统必须独立于他所创建的对象的生成方式,或它需要与对种对象类型一同工作。下面我们修改上述的车辆工厂方法至抽象车辆工厂方法 AbstractVehicleFactory。在这个例子中,我们不在限定车辆工程的车辆类型,而是可以通过用户 (注册/获取) 来操作车辆类型,请看下面的例子:
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 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 function Car (options ) { this .doors = options.doors || 4 ; this .state = options.state || 'brand new' ; this .color = options.color || 'silver' ; } Car.prototype.drive = function ( ) { }; Car.prototype.breakDown = function ( ) { }; function Truck (options ) { this .state = options.state || 'used' ; this .wheelSize = options.wheelSize || "large" ; this .color = options.color || "blue" ; } Truck.prototype.drive = function ( ) { }; Truck.prototype.breakDown = function ( ) { }; 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; if (proto.drive && proto.breakDown) { types[type] = Vehicle; } return AbstractVehicleFactory; } } })(); AbstractVehicleFactory.registerVehicle("car" , Car); AbstractVehicleFactory.registerVehicle("truck" , Truck); var car = AbstractVehicleFactory.getVehicle('car' , { color: "green" , state: "new" }); console .log(car instanceof Car);console .log(car);var truck = AbstractVehicleFactory.getVehicle('truck' , { wheelSize: "medium" , color: "yellow" }); console .log(truck instanceof Truck);console .log(truck);
以上便实现了抽象工厂方法 AbstractVehicleFactory