网络编程
位置:首页>> 网络编程>> JavaScript>> 小议javascript设计模式(5)

小议javascript设计模式(5)

作者:oldfish 来源:alipay UED 发布时间:2009-10-09 13:31:00 

标签:设计模式,JavaScript,接口,组合模式

Javascript设计模式之装饰者模式

装饰者模式:可以不创建新的子类,给对象创建新的功能。举例说明:支付宝收银台红包结合余额付款的应用场景。

var Ieconomics = new Interface("ieconomics",[["getPrice"]]);

首先创建一个组件类,基与该组件实例化的对象,会被作为参数传递给装饰者类,以便装饰者调用到该组件中的各方法。

  var economic = function(){ 
     Interface.regImplement(this,Ieconomics); 
   }; 
    economic.prototype={ 
        getPrice:function(){ 
          //代码实现 
        } 
    };

然后创建一个装饰者抽象类,作为派生装饰者选件类的父类:  

var economicsDecorator = function(economic){ 
      this.economic = economic; 
      this.regImplement(economic,Ieconomics); 
   }; 
    economicsDecorator.prototype={ 
        getPrice:function(){ 
          return this.economic.getPrice(); 
        } 
    };

最后基于上面这个抽象类,派生出一个装饰者选件类:

//红包装饰者选件类 
   var coupon = function(economic){ 
      //调用装饰着抽象类的构造函数 
      economicsDecorator.call(this,economic); 
   }; 
   extend(coupon,couponDecorator); 
   coupon.prototype=function(){ 
       //改写getPrice方法 
       getPrice:function(){ 
         return this.economic.getPrice() - this.getCoupon(); 
       }, 
       getCoupon:function(){ 
         //获取红包总价具体实现       
       } 
   };

var myCoupon = new economic(); 
    myCoupon = new coupon(myCoupon);

实现装饰者模式就是这么简单,首先创建一个组件的实例myCoupon,然后将该对象作为参数传递给装饰者选件类coupon。你会发现两句代码中我都把值赋给了变量myCoupon,这是因为他们都实现了同一个接口类,他们之间是可以互换使用的。

看到这里心细的同学可能会发现,我们在coupon类中新增了一个getCoupon方法,目前来看不会有任何问题,但是如果我们继续创建一个购物卷装饰者选件类,然后结合红包一起用呢?

//购物卷装饰者选件类 
   var voucher = function(economic){ 
     economicsDecorator.call(this,economic); 
   }; 
   extend(voucher,couponDecorator); 
   voucher.prototype=function(){ 
       getPrice:function(){ 
         return this.getPrice() - this.getVoucher(); 
       }, 
       getVoucher:function(){ 
         //获取优惠卷总价具体实现       
       } 
   };

var myCoupon = new economic(); 
    myCoupon = new coupon(myCoupon); 
    myCoupon = new voucher(myCoupon);

在这种场景下面getCoupon方法已经找不到了,这是因为voucher装饰myCoupon的时候,它的父类economicsDecorator不包含getCoupon方法,那自然是取不到的了,那该怎么办呢?

分析一下装饰者抽象类economicsDecorator,我们传递了一个myCoupon的引用作为参数,我们可以通过这个参数做一些小动作,获得新增加的方法。

var economicsDecorator = function(economic){ 
      this.economic = economic; 
      this.interface = Ieconomics; 
      for(var k in this.economic){ 
       if(typeof this.economic[key] !== "function"){ 
        continue; 
        var i; 
        for(i = 0;len = this.interface.methods.length,i < len; i++) { 
            //通过遍历比较在接口类中是否包含此方法,如果包含返回下一个 
            if(key == this.interface.methods[i][0]) {  
                break; 
            } 
        } 
        if(i < this.interface.methods.length) 
         continue; 
         var decorator = this; 
         //采用匿名函数调用方式来定义新方法 
         (function(methodName) { 
            decorator[methodName] = function() { 
                return decorator.economic[methodName](); 
            }; 
         })(key); 
        } 
       }  
      } 
      this.regImplement(economic,Ieconomics); 
   }; 
   economicsDecorator.prototype={ 
        getPrice:function(){ 
          return this.economic.getPrice(); 
        } 
    };

看上面的代码,我们对装饰者抽象类做了一些修改,这样做是为了确保在装饰者选件类中一旦定义新方法,可以在装饰者抽象类中动态的定义出来。这里只是提供一个使用装饰者模式的思路,具体的实现代码远比这个复杂,由于项目还在开发中,demo暂不提供,支付宝新版收银台发布后,会跟大家再做个详细的设计分享。

0
投稿

猜你喜欢

手机版 网络编程 asp之家 www.aspxhome.com