小议javascript设计模式(5)
作者:oldfish 来源:alipay UED 发布时间:2009-10-09 13:31:00
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暂不提供,支付宝新版收银台发布后,会跟大家再做个详细的设计分享。
猜你喜欢
- 由于Oracle自身比较复杂,在Linux环境下安装要涉及很多方面的因素。本文分两个方面介绍在Linux RedHat 6.0环境下Orac
- 数据库快照是怎样工作的可以使用典型的数据库命令CREATE DATABASE语句来生成一个数据库快照,在声明中有一个源数据库快照的附加说明。
- 外观模式(Facade Pattern)是什么外观模式是一种结构型模式,它提供了一个简单的接口,隐藏了系统的复杂性,为客户端提供了一个简单的
- 实体有五种预定义的XML实体,HTML编码者应该熟悉。XML文档中的字符&、<、>、"和'被分别表示为
- 这篇论坛文章(赛迪网技术社区)详细讲解了SQL Server海量数据导入的最快方法,更多内容请参考下文:最近做某项目的数据库分析,要实现对海
- 1:使用SHOW语句找出在服务器上当前存在什么数据库:mysql> SHOW DATABASES;2:2、创建一个数据库MYSQLDA
- 互联网上不计其数的信息本质上都是一个一个的HTML文档组成的,通过链接将它们串联起整个互联网。这就犹如骨肉之于人体一样,只有通过经脉才能将它
- 写在前面:本节主要讲述一些基本的,常用的SQL语句,而非数据库方面的基本知识。数据库方面的知识留待以后再讲,现在就我们平常常用的一些SQL语
- sysdate+(5/24/60/60) 在系统时间基础上延迟5秒 sysdate+5/24/60 在系统时间基础上延迟5分钟 sysdat
- 今天在看见了一堆不错的非洲的web 2.0网站的Logo,于大家一起欣赏:非洲web2.0网站的logo大部分和平时看见的web2.0网站l
- 本文介绍了一些JavaScript常用到得表单验证函数,方便大家使用。 判断是否为整数,是则返回true,否则返回falsefun
- 大家好,我叫斑马纹列表中使用两种相同的样式但颜色不同的背景,来间隔显示的内容。当然这个释义我是借鉴《designing interfaces
- 一.脚本基础1.USE语句设置当前数据库。2.声明变量语法:DECLARE @变量名 变量类型在声明变量后,给变量赋值之前,变量的值为NUL
- 在使用mysql视图是出现问题: The user specified as a definer ('root'@'
- GetRepeatTimes(TheChar,TheString) 得到一个字符串在另一个字符串当中出现几次的函数(新)如:response
- SQL的扩展的删除与恢复 删除 代码如下:use master exec spdropextendedproc “xpcmdshell“ e
- 前段时间做一个小项目碰到了一个导航制作的方式然后突然想到曾经很久以前看到的梯形状的不规则导航,就尝试做了一下。结果碰到了几个问题,后来在同事
- Silverlight和Flash,到底谁更强?谁更有优势?很多初接触Silverlight和Flash的人总是会问这个问题,因为它们在表面
- 阅读上一篇:你是真正的用户体验设计者吗? Ⅵ很可怕,是吧!图中翻译:(从内到外)第一层:用户体验第二层:内容管理界面设计顾客关系管理交互设计
- 一、get//get请求function getUrl($url, $header = []){ $ch = cu