工厂模式
本章讨论两种工厂模式:
简单工厂模式
使用一个类(通常是一个单体)来生成实例。
使用场景:假设你想开几个自行车商店(创建自行车实例,组装它,清洗它,出售它),每个店都有几种型号的自行车出售。
/*=====================实现车==========================*/ var Bicycle = new Interface('Bicycle', ['assemble', 'wash', 'ride', 'repair']);//Interface见2.初识接口那一章的用鸭式辨型模仿接口 var Speedster = function(){ //实现Bicycle接口 }; Speedster.prototype = { assemble: function(){ }, wash: function(){ }, ride: function(){ }, repair: function(){ } }; /*=====================实现商店========================*/ 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); //Interface见2.初识接口那一章的用鸭式辨型模仿接口 return bicycle; } } var BicycleShop = function(){}; BicycleShop.prototype ={ sellBicycle: function(model){ var bicycle = BicycleFactory.createBicycle(model); //调用工厂 bicycle.assemble(); bicycle.wash(); return bicycle; } }; /*=====================开始卖车========================*/ var shop1 = new BicycleShop(); var soldBicycle = shop1.sellBicycle('The Speedster');
其实,我们完全可以将BicycleFacotry的实现放在BicycleShop.prototype中,那么,为什么会用上工厂模式?
用工厂模式之后就更加方便管理,当我们需要添加一种新的车型时,只需修改工厂就可以了,省得我们去修改BicycleShop。
复杂工厂模式
使用子类来决定一个成员变量应该是哪个具体的类的的实例(按照正式的定义,工厂是一个将其成员对象的实例化推迟到子类中进行的类)
同样的场景,我们打算让各个自行车商店自行决定从哪个生产厂家进货。
我们把BicycleShop设计为抽象类,让子类根据各自的进货渠道实现其createBicycle方法。
/*=============================实现商店=================================*/ /*=============抽象类BicycleShop============*/ 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.'); } }; /*===========商店从Acme公司进货=============*/ var AcmeBicycleShop = function() {}; extend(AcmeBicycleShop, BicycleShop); //extend见4.继承(概念) AcmeBicycleShop.prototype.createBicycle = function(model){ var bicycle; switch(model){ case 'The Speedster': bicycle = new AcmeSpeedster(); break; case 'The Lowrider': bicycle = new AcmeLowrider(); break; case 'The Comfort Cruiser': default: bicycle = new AcmeComfortCruiser(); } Interface.ensureImplements(bicycle, Bicycle); return bicycle; }
这里只是实现了商店,至于自行车的实现如上,就不再重复。
工厂模式的适用场合
创建对象的最简单的方法是使用new关键字和具体类.如果不知道工厂模式的适用场合,那么创建和维护工厂所带来的额外复杂性是得不偿失的.
动态实现
如果要像前面自行车的例子一样,创建一些用不同方式实现同一接口的对象,那么可以使用一个工厂方法或简单工厂对象来简化实现的过程.
节省设置开销
如果对象需要进行复杂并且彼此相关的设置,那么使用工厂模式可以减少每种对象所需的代码量.
如果这种设置只需为特定类型的所有实例执行一次即可,这种作用尤其突出.
如果所用的类要求加载外部库的话,这尤其有用.工厂方法可以对这些库进行检查并动态加载那些未找到的库.
这种设置只存在于一个地方,因此以后改起来也方便很多.
用许多小型对象组成一个大对象
工厂方法可以用来创建封装了许多较小对象的对象.
例如自行车包含许多更小的系统:车轮,车架,车闸等.如果你不想让某个子系统与较大的那个对象之间形成强耦合,而是想在运行是从许多子系统中进行挑选的话,那么工厂模式是一个理想的选择.