工厂模式
2016-04-23 17:19
357 查看
文中示例代码引用自《Javascript设计模式》一书
这样,当产生新种类自行车的商店时,我们只需要改变BicycleShop.createBicycle函数,即
而不是改变一个BicycleShop大类,这样一来耦合性大大降低。
再比如现在除了增加不同类别自行车的店,还增加了不同进货渠道的信息,不同的进货渠道的自行车在不同的店卖,不同类别的自行车也在不同的店卖。
我们通过继承,来分别定义不同进货渠道下,不同类自行车的所在店。比如有两个进货渠道,Acme和General Products公司。
则这两个进货渠道分别继承BicycleShop这一类。
注意,该模式并非什么时候都是合适的模式,当以下两种情况时,最好用new关键字和构造函数公开进行实例化,这样可以简化代码结构,增强代码的易读性,可以一眼就看到调用的是什么构造函数,而不用去查看某个工厂方法才能知道实例化的是什么类。
根本不可能另外换用该类
不需要在运行期间在可互换类中动态进行选择时,
使用工厂模式的目的
消除对象间的耦合,简化更换所使用的类的工作以及简化在运行期间动态选择所用类的工作。(即弱化对象间耦合以及防止代码的重复)工厂模式的思路
先创建出所要用到的小对象,然后生成并返回包含这些小对象的容器,即大对象。示例
自行车商店
非工厂模式
不同自行车店,卖不同类自行车var BicycleShop = function () { }; BicycleShop.prototype = { sellBicycle: 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); bicycle.assemble(); bicycle.wash(); return bicycle; } };无论哪家自行车店,都具有该服务,即各类自行车店都实现了该自行车接口。
var Bicycle = new Interface('Bicycle', ['assemble', 'wash', 'ride', 'repair']); var Speedster = function () { ...}; Speedster.prototype={ assemble:function(){ ... }, wash:function(){ ... }, ride:function(){ ...}, repair:function(){ ... } };有某种自行车,要卖掉
var californiaCruisers = new BicycleShop(); var yourNewBike = californiaCruisers.sellBicycle('The Speedster');若现在增加了某个新的种类的自行车店,则需要对BIcycleShop这一个大类进行更改,即代码的耦合性较高,牵一发而动全身
工厂模式
经常发生变动的小对象被分离出来,生成一个函数var BicycleShop = function () { }; BicycleShop.prototype = { sellBicycle: function (model) { var bicycle=this.createBicycle(model); bicycle.assemble(); bicycle.wash(); return bicycle; }, 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; } };
这样,当产生新种类自行车的商店时,我们只需要改变BicycleShop.createBicycle函数,即
BicycleShop.createBicycle=function (model) { var bicycle; switch (model) { case 'The Speedster': bicycle = new Speedster(); break; case 'The Lowrider': bicycle = new Lowrider(); break; case 'The FlatLander': bicycle = new Flatlander(); break; case 'The Comfort Cruiser': default: bicycle = new ComfortCruiser(); } Interface.ensureImplements(bicycle, Bicycle); return bicycle; }
而不是改变一个BicycleShop大类,这样一来耦合性大大降低。
再比如现在除了增加不同类别自行车的店,还增加了不同进货渠道的信息,不同的进货渠道的自行车在不同的店卖,不同类别的自行车也在不同的店卖。
我们通过继承,来分别定义不同进货渠道下,不同类自行车的所在店。比如有两个进货渠道,Acme和General Products公司。
则这两个进货渠道分别继承BicycleShop这一类。
var AcmeBicycleShop = function () { }; extend(AcmeBicycleShop, BicycleShop); 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 FlatLander': bicycle = new AcmeFlatlander(); break; case 'The Comfort Cruiser': default: bicycle = new AcmeComfortCruiser(); } Interface.ensureImplements(bicycle, Bicycle); return bicycle; }
var GeneralProductsBicycleShop = function () { }; extend(GeneralProductsBicycleShop, BicycleShop); GeneralProductsBicycleShop.prototype.createBicycle = function (model) { var bicycle; switch (model) { case 'The Speedster': bicycle = new GeneralProductsSpeedster(); break; case 'The Lowrider': bicycle = new GeneralProductsLowrider(); break; case 'The FlatLander': bicycle = new GeneralProductsFlatlander(); break; case 'The Comfort Cruiser': default: bicycle = new GeneralProductsComfortCruiser(); } Interface.ensureImplements(bicycle, Bicycle); return bicycle; }
XHR工厂的动态定义函数
var AjaxHandler = new Interface('AjaxHandler', ['request', 'createXhrObject']); var SimpleHandler = function () {}; SimpleHandler.prototype={ request:function(method,url,callback,postVars){ var xhr=this.createXhrObject(); xhr.onreadystatechange=function(){ ... }; xhr.open(method,rul,true) }, createXhrObject:function(){ var methods=[ function(){return new XMLHttpRequest();}, function(){return new ActiveXObject('Msxml2.XMLHTTP');}, function(){return new ActiveXObject('Microsoft.XMLHTTP');} ]; for(var i=0,len=methods.length;i<len;i++){ try{ methods[i](); } catch(e){ continue; } this.createXhrObject=methods[i]//memoize the method。 //运行过一次该位置后,实例化对象.createXhrObject就根据其首次运行的浏览器环境被指向对应的方法了 //再次执行request函数时,其调用的createXhrObject函数就是这个被赋值的函数,而不用再重新判断一遍 //即动态定义函数 return methods[i]; throw new Error('SimpleHandler:Could not create an XHR object') } } }
注意,该模式并非什么时候都是合适的模式,当以下两种情况时,最好用new关键字和构造函数公开进行实例化,这样可以简化代码结构,增强代码的易读性,可以一眼就看到调用的是什么构造函数,而不用去查看某个工厂方法才能知道实例化的是什么类。
根本不可能另外换用该类
不需要在运行期间在可互换类中动态进行选择时,
相关文章推荐
- MySQL 数据库 常用函数
- 使用TexturePackerGUI配合NGUI打包图集
- 中外饮食类英语单词大全
- 背包问题-堆栈-找出其中一组解(总体积为T,n件物品体积分别是w1,w2,...,w2n,找出若干件恰好装满背包)
- Android Services 创建一个Bound服务
- 团队开发——个人工作总结05
- 全局侧滑
- 欢迎使用CSDN-markdown编辑器
- Eclipse下Genymotion模拟器的安装
- 有赞搜索引擎实践(算法篇)
- ArcGIS Desktop 高(新)版本数据库迁移到较低(旧)版本数据库操作方法
- Less函数说明
- 343. Integer Break 【M】
- 【BZOJ1194】[HNOI2006]潘多拉的盒子【BFS】【SCC】【拓扑排序】【DAG最长路】【自动机】
- Exchange 2016集成ADRMS系列-12:域内outlook 2010客户端测试
- 开源新闻速递(160423):Ubuntu 16.04 各个主要分支发布,有的分支面临消亡
- 第九周项目1—深复制体验(2)
- 萬 影 皆 因 月
- 第一冲刺阶段站立会议07
- 浅谈Android移动开发程序员的职业发展之路