小议javascript 设计模式 推荐(3)


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();
Javascript设计模式之组合模式
组合模式:运用该设计模式可以通过组合对象添加属性和方法,通过递归批量式的让叶子对象得到组合对象的属性和方法。打个比方我们现在要动态创建一个银行列表,按银行类型分为网上银行类,卡通银行类,并可配置他们是否显示。用组合模式如何实现呢?
第一步还是先定义接口,因为要做到某类银行甚至某个银行是否显示可配置,那么我们先约定2个接口,showBank和hideBank。
var IcardItem = new Interface(”icardItem”,[["showBank"],["hideBank"]]);
接下来先定义卡的组合对象,并设置组合对象的基本方法add,remove,getChild,由于这个类继承了IcardItem接口类,所以还定义了showBank,hideBank这两个接口方法。

复制代码 代码如下:


var cardMain = function(id){
this.cards = [];
this.element = document.createElement("div");
this.element.id = id;
Interface.regImplement(this,IcardItem);
};
cardMain.prototype = {
add:function(card){
this.cards.push(card);
this.element.appendChild(card.getElement());
},
remove:function(card){
for(i=0;len=this.cards.length,i<len;i++){
if(cards[i] == card){
this.cards.splice(i,1);
break;
}
this.element.removeChild(card.getElement());
}
},
getChild:function(i){
return this.cards[i];
},
getElement:function(){
return this.element;
},
showBank:function(){
this.element.style.display ="block";
for(i=0;len=this.cards.length,i<len;i++){
this.cards[i].showBank();
}
},
hideBank:function(){
this.element.style.display ="none";
for(i=0;len=this.cards.length,i<len;i++){
this.cards[i].hideBank();
}
}
};


然后定义叶子对象类bankLogo用以创建银行logo,这里银行logo都以带class的a标签标识:

复制代码 代码如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wjywxd.html