一个类或者对象中,往往会包含别的对象。在创建这种对象的时候,你可能习惯于使用常规方式,即用 new 关键字和类构造函数。
这会导致相关的俩个类之间产生依赖。
工厂模式,就是消除这俩个类之间的依赖性的一种模式,它使用一种方法来决定究竟实例化那个具体的类。
简单工厂模式
假设你想开几个自行车商店,每个商店都有几种型号的自行车出售,可以用这样一个类来表示:
var BicycleShop = function(){} BicycleShop.prototype = { sellBicycle:function(model){ var bicycle; switvh(model){ case 'The Speedster': bicycle = new Speedster(); break; case 'The Lowrider': bicycle = new Lowrider(); break; case 'The Comfort Cruiser': default: bicycle = new ComfortCruiser(); } Interface.ensureImplements(bicycle,Bicycle); bicycle.assemble(); bicycle.wash(); return bicycle; } }
sellBicycle 方法根据所要求的自行车型号用 switch 来创建实例。
Bicycle接口:
var Bicycle = new Interface('Bicycle',['assemble','wash','ride','repair']);
Speedster 类:
var Speedster = function(){ ... }; Speedster.prototype = { assemble:fucntion(){ ... }, wash:fucntion(){ ... }, ride:fucntion(){ ... }, repair:fucntion(){ ... } } var californiaCruisers = new BicycleShop(); var yourNewBike = californiaCruisers.sellBicycle('The Speedster');
如果想加入一款新型号的车,只能修改BicycleShop的代码了。最好的办法就是把sellBicycle方法中“创建新实例”这部分工作转交给一个简单工厂对象:
var BicycleFactory = { createBicycle:function(model){ var bicycle; switch(model){ case 'The Speedster': bicycle = new Speedster(); break; case 'The Lowrider': bicycle = new Lowrider(); break; case 'The Comfort Cruiser': default: bicycle = new ComfortCruiser(); } Interface.ensureImplements(bicycle,Bicycle); return bicycle; } }
BicycleFactory是一个单体,用来把createBicycle封装在一个命名空间中,这个方法返回一个实现了Bicycle接口的对象。然后你可以照常对其进行组装和清洗。
var BicycleShop = function(){} BicycleShop.prototype = { sellBicycle:function(model){ var bicycle = BicycleFactory.createBicycle(model); bicycle.assemble(); bicycle.wash(); return bicycle; } }
这样,有关提供车型的所有信息都集中到一个地方管理,所以添加更多车型很容易。
BicycleFactory 就是简单工厂的一个很好的例子,这种模式把成员对象的创建工作转交给一个外部对象。这个外部对象可以像本例一样是一个简单的命名空间,也可以是一个类的实例。
真正的工厂模式
真正的工厂模式与简单的工厂模式区别在于,它不是另外使用一个类或者对象来创建自行车,而是使用一个子类。
按照正常定义,工厂是一个将其成员对象的实例化推迟到子类中进行的类。
我们打算让自行车商店自己决定从那个生产厂家进货。出于这个原因,单单一个BicycleFactory对象将无法提供需要的所有自行车实例。我们可以把BicycleShop设计为抽象类,然后让子类根据各自的进货渠道实现其createBicycle方法:
var BicycleShop = function(){} BicycleShop.prototype = { sellBicycle:function(model){ var bicycle = this.createBicycle(model); bicycle.assemble(); bicycle.wash(); return bicycle; }, createBicycle:function(model){ throw new Error('Unsupported operation on an abstract class.'); } }
以上类中定义了createBicycle方法,但是调用这个方法,会抛出一个错误,现在BicycleShop是一个抽象类,它不能被实例化,只能用来派生子类。
设计一个经销特定自行车生产厂家产品的子类需要扩展 BicycleShop 方法,下面是扩展方法。
var AcmeBicycleShop = function(){}; extend(AcmeBicycleShop,BicycleShop); AcmeBicycleShop.prototype.createBicycle = function(model){ var bicycle; switch(model){ case 'The Speedster': bicycle = new AcmSpeedster(); break; case 'The Lowrider': bicycle = new AcmLowrider(); break; case 'The Comfort Cruiser': default: bicycle = new AcmComfortCruiser(); } Interface.ensureImplements(bicycle,Bicycle); return bicycle; } var alecsCruisers = new AcmeBicycleShop(); var yourNewBike = alecsCruisers.sellBicycle('The Lowrider');
对Bicycle进行的一般性操作的代码完全可以放在父类BicycleShop中,而对具体的Bicycle对象进行实例化的工作则被留到子