小议javascript设计模式(3)
作者:oldfish 来源:alipay UED 发布时间:2009-10-09 13:31:00
Javascript设计模式之工厂模式Factory
工厂模式Factory:先创建一个抽象类,然后基于这个抽象类派生出子类,并在子类中创建工厂方法,从而把实例化推迟到对应的子类中进行,说实话,工厂模式在javascript中的应用有些牵强,毕竟javascript不像java存在硬编码带来的困搅,要学习的只是模式的思想,切忌因为模式而模式。
不妨举个偏激点的例子,为tab切换、下拉列表等组件添加定位,渐隐,延迟等效果,我们可以先为这些组件定义一个接口:
var Iwidget = new Interface("iwidget",[["addEffect"]]);
定义该接口,以便之后派生的子类继承,接口中定义了一个addEffect方法,接口方法实现后,调用的同学大可不必关注各子类中对于addEffect方法的代码实现。
var Widget = function(){};
Widget.prototype={
fire:function(model){
var widget = this.createWidget(model);
//有同学问为什么子类都必须定义接口方法,因为下面要调用嘛
widget.addEffect();
return widget;
},
show:function(){
//show代码具体实现
},
hide:function(){
//hide代码具体实现
},
createWidget:function(model){
alert('抽象类,不可以实例化')
}
};
上例先定义一个抽象类Widget,做为派生子类的父类,由于考虑到这两类组件都涉及到隐藏和显示一个容器,所以在父类中预先定义好show和hide方法以便子类继承。
var xTab = function(){};
extend(xTab,Widget);
xTab.prototype.createWidget = function(model){
var widget;
switch(model){
case 'position':
widget = new xTabPosition();
break;
case 'anim':
widget = new xTabAnim();
break;
case 'delay':
default:
widget = new xTabDelay();
}
};
var dropDown = function(){};
extend(dropDown,Widget);
dropDown.prototype.createWidget = function(model){
var widget;
switch(model){
case 'position':
widget = new dropDownPosition();
break;
case 'anim':
widget = new dropDownAnim();
break;
case 'delay':
default:
widget = new dropDownDelay();
}
};
子类xTab和dropDown继承了父类,并且重写了createWidget方法,不同的子类根据定位,渐隐,延迟效果分别创建不同的实例,只要创建这些实例的类都实现接口中约定的addEffect方法,至于方法代码如何实现,千篇一律,爱咋整咋整。
var xTabPosition = function(){};
xTabPosition.prototype ={
addEffect:function(){
//具体实现代码
}
};
var dropDownPosition = function(){};
dropDownPosition.prototype ={
addEffect:function(){
//具体实现代码
}
};
var dropDownInstance = new dropDown();
dropDownInstance.fire('position');
以此类推,如果您需要为气泡组件添加这些效果,照葫芦画瓢就可以了,说到这里你可以清楚的看到,这种设计模式大大降低了类和类之间的耦合度,而且可以根据具体的交互需求,实现不同的辅助动作,但是也无可避免的增加了代码实现上的复杂性,事实上这种模式并不适合javascript,毕竟它有别于java,不会有类名硬编码的问题,目的是学习他的设计思想,所以以上示例仅供参考,如无大人在旁,小朋友切勿效仿。
对于javascript爱好者来说,更有价值的应该是工厂模式中讲到的的”缓存(memoization)机制”,书上举了个创建XHR对象的例子来说明该特性,但是效果显然不够明显……
memoization名词解释:把函数的每次执行结果都放入一个键值对(数组也可以,视情况而定)中,在接下来的执行中,在键值对中查找是否已经有相应执行过的值,如果有,直接返回该值,没有才 真正执行函数体的求值部分。很明显,找值,尤其是在键值对中找值,比执行函数快多了
在递归调用的时候,memoization的威力才能更好的显现。下面是一个经典的斐波纳契序列,fib(20) 会把fib这个方法执行21891次,如果是fib(40),这会执行331160281次。
function fib(n) {
if (n < 2) {
return n;
}
return fib(n - 1) + fib(n - 2);
}
再看看如何使用memoization来实现:
var iterMemoFib = (function() {
var cache = [1, 1];
var fib = function(n) {
if (n >= cache.length) {
//将一个递归转换成了一个
for (var i = cache.length; i <= n; i++) {
cache[i] = cache[i - 2] + cache[i - 1];
}
}
return cache[n-1];
}
return fib;
})();
将Function的原型扩展memoize 和unmemoize 方法,这样你可以对任何函数实现memoize和解除memoize,当然,这个方法要慎,对一些不是频繁执行的函数,没必要缓存:
Function.prototype.memoize = function() {
var pad = {};
var self = this;
var obj = arguments.length > 0 ? arguments[i] : null;
var memoizedFn = function() {
// 把参数作为数组保存,作为键,把函数执行的结果作为值缓存起来
var args = [];
for (var i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
}
if (!(args in pad)) {
pad[args] = self.apply(obj, arguments);
}
return pad[args];
}
memoizedFn.unmemoize = function() {
return self;
}
return memoizedFn;
}
Function.prototype.unmemoize = function() {
alert("Attempt to unmemoize an unmemoized function.");
return null;
}
使用方法:fib.memoize();
猜你喜欢
- 作为前端开发工程师,平时对于Dom的查找遍历和操作是家常便饭。对于优秀的前端来说,也肯定早已有了自己的一套方法来封装这些重复的操作。但是,现
- <script type="text/javascript">/*<![CDAT
- 下载了一个小型的记帐软件,发现这个软件数据库用的是access,很想看看它的数据库结构怎样,结果人家加密了。access的解密小case了,
- 自从2005年8月11日阿里巴巴宣布收购雅虎中国的全部资产后,做为阿里巴巴集团的创始人马云心里盘算的事应该是如何把雅虎中虎整合进阿里巴巴这个
- 在这个擦亮自己的眼睛去看SQL Server的系列中的第二篇中提过要写历史渊源,这里的历史主要描述的是数据库本身的历史与SQL Server
- win7 +Navicat Lite 9+ VMware7在VMware中安装openSUSE11.x mysql5 Navicat Lit
- 本文通过一个详细的例子,来阐述了在线编辑XML文档数据的方法。由于Netscape对XML的支持比较弱,因此,要实现跨平台的数据交换,数据的
- 手痒痒系列之简单的放大镜写了个放大镜功能,可以设置显示的宽高width,height显示的位置,float ‘left’ 'righ
- <%'***********************************************'函数
- 就我个人经验来讲:除了oracle,没有比HP 客户支持中心更糟糕的体验了。刚买不到一个月的HP MINI笔记本,莫名其妙键盘上的引号键松动
- 我想让一片文章,每到3000字就分到下一条插入到数据库,求高手 <%Dim Content Conte
- Web设计师可以使用HTML4和CSS2.1完成一些很酷的东西。我们可以在不使用陈旧的基于table布局的基础上完成文档逻辑结构并创建内容丰
- 内容摘要: ASP具备管理不同语言脚本程序的能力,能够自动调用合适的脚本引擎以解释脚本代码和执行内置函数。ASP开发环境提供了两种
- 我们日常用CSS布局的时候,关于图片背景,大部分的人都是一个背景一张图片的,怎么说呢?这是很标准的方法,但是这种普通制作方式下要保存大量图片
- 一:最近,经常碰到有网友问,如何使vbscript和javascipt传递变量。不知道为什么要这么做。因为每一种脚本语言几乎都可以完成所需要
- ASP开发中有用的函数(function)集合,挺有用的,请大家保留!'******************************
- 作用:用ASP程序将页面中的电话号码生成图片格式。 代码如下:<% Call Com_CreatValidCode
- QQ影音至9月发布之后一直口碑很好,视觉界面和交互设计也颇受好评,这是设计师们努力的结果,也是众多用户反馈的功劳。我们希望可以提供更多价值回
- staytime.asp<% If Request.QueryString("time")&n
- 前些日子在SmashingMagazine看到一篇关于CSS3新技术不错的文章,它详细介绍了CSS3的新特性和它的使用方法,它包括:浏览器专