装饰模式:在不改变原类(对象)和继承的情况下动态扩展对象功能,通过包装一个对象来实现一个新的具有原对象相同接口的新的对象。
在设计原则中,有一条,多用组合,少用继承,装饰模式正是这一原则的体现。

UML示意图:

假设自行车商店有4种自行车卖:

var ABicycle = function(){ ... };
var BBicycle = function(){ ... };
var CBicycle = function(){ ... };
var DBicycle = function(){ ... };

自行车商店需要给自行车加些配件,比如车筐,尾灯等,如果给每一类自行车创建一个子类:

var ABicycleWithBell = function(){ ... };
var BBicycleWithBasket = function(){ ... };
var CBicycleWithLight = function(){ ... };

带有铃铛的A类车,带有车筐的B类车,带有尾灯的C类车,导致的结果,就是N种配置会有4N个子类,当然不是一个可取的方法。
可以将铃铛等东西设置为实例属性,但是对于方法的扩展,比如变速等,就可以使用装饰模式。

A类自行车:

function ABicycle(){ }

ABicycle.prototype = {
wash : function(){ },
ride : function(){ },
getPrice : function(){
return 888;
}
}

铃铛:

function bicycleBell( bicycle ){
var price= bicycle.getPrice();
bicycle.bell = function(){
console.log("ding! ding!");
};
bicycle.getPrice = function(){
return price + 100;
};
return bicycle;
}

加铃铛:

var bicycleA = new ABicycle();
bicycleA = bicycleBell( bicycleA );

如果是:

bicycle.getPrice = function(){
return bicycle.getPrice() + 100;
};

会导致无限循环调用,换个方法:

function BicycleBell( bicycle ){
this.bicycle = bicycle;
} BicycleBell.prototype = {
wash : function(){
return this.bicycle.wash();
},
ride : function(){
return this.bicycle.ride();
},
getPrice : function(){
return this.bicycle.getPrice() + 100;
},
bell : function(){
console.log("ding! ding!");
}
}

包装对象,再次模拟原对象,这种方式较好的解决了对于某些需要修改并且依赖原始该方法的方法生成形式。但是有点繁琐,可以提取一下,通用继承函数:

function extend( subClass, superClass ){
var F = function(){};
F.prototype = superClass.prototype;
subClass.prototype = new F();
subClass.prototype.constructor = subClass;
subClass.superclass = superClass.prototype;
if( superClass.prototype.constructor === Object.prototype.constructor ){
superClass.prototype.constructor = superClass;
}
}

装饰角色:

function BicycleDecorator( bicycle ){
this.bicycle = bicycle;
}
BicycleDecorator.prototype = {
wash : function(){
return this.bicycle.wash();
},
ride : function(){
return this.bicycle.ride();
},
getPrice : function(){
return this.bicycle.ride();
}
}

使用extend:

var BicycleBell = function( bicycle ){
BicycleBell.superclass.constructor.call( this, bicycle );
}
extend( BicycleBell, BicycleDecorator ); BicycleBell.prototype.bell = function(){
console.log("ding! ding!");
}
BicycleBell.prototype.getPrice = function(){
return this.bicycle.getPrice() + 100;
}

装铃铛:

var bicycleA = new ABicycle();
bicycleA = new BicycleBell( bicycleA );

装饰者模式是为已有功能动态地添加更多功能的一种方式,把每个要装饰的功能放在单独的函数里,然后用该函数包装所要装饰的已有函数对象,因此,当需要执行特殊行为的时候,调用代码就可以根据需要有选择地、按顺序地使用装饰功能来包装对象。优点是把类(构造函数)的核心职责和装饰功能区分开了。

javascript设计模式-装饰模式的更多相关文章

  1. JavaScript设计模式 -- 读书笔记

    JavaScript设计模式 一. 设计模式 一个模式就是一个可重用的方案: 有效的解决方法.易重用.善于表达该解决方案: 未通过"模式特性"测试的模式称为模式原型: 三规则:适用 ...

  2. 《JavaScript设计模式 张》整理

    最近在研读另外一本关于设计模式的书<JavaScript设计模式>,这本书中描述了更多的设计模式. 一.创建型设计模式 包括简单工厂.工厂方法.抽象工厂.建造者.原型和单例模式. 1)简单 ...

  3. 《JavaScript设计模式与开发实践》整理

    最近在研读一本书<JavaScript设计模式与开发实践>,进阶用的. 一.高阶函数 高阶函数是指至少满足下列条件之一的函数. 1. 函数可以作为参数被传递. 2. 函数可以作为返回值输出 ...

  4. Javascript设计模式学习一

    学习Javascript设计模式之前,需要先了解一些相关知识,面向对象的基础知识.this等重要概念,以及掌握一些函数式编程的技巧. Js多态 多态的思想:实际上是把“做什么”和“谁去做”分离开来.例 ...

  5. javascript设计模式实践之职责链--具有百叶窗切换图片效果的JQuery插件(三)

    在上一篇<javascript设计模式实践之模板方法--具有百叶窗切换图片效果的JQuery插件(二)>里,通过采用模板方法模式完成了切换效果对象的构建编写. 接下来就是完成各效果对象的调 ...

  6. javascript设计模式实践之模板方法--具有百叶窗切换图片效果的JQuery插件(二)

    在上一篇<javascript设计模式实践之迭代器--具有百叶窗切换图片效果的JQuery插件(一)>里,通过采用迭代器模式完成了各初始化函数的定义和调用. 接下来就要完成各个切换效果的编 ...

  7. javascript设计模式实践之迭代器--具有百叶窗切换图片效果的JQuery插件(一)

    类似于幻灯片的切换效果,有时需要在网页中完成一些图片的自动切换效果,比如广告,宣传,产品介绍之类的,那么单纯的切就没意思了,需要在切换的时候通过一些效果使得切换生动些. 比较常用之一的就是窗帘切换了. ...

  8. 常用的Javascript设计模式

    <parctical common lisp>的作者曾说,如果你需要一种模式,那一定是哪里出了问题.他所说的问题是指因为语言的天生缺陷,不得不去寻求和总结一种通用的解决方案. 不管是弱类型 ...

  9. Javascript设计模式(摘译)

    说明: 未完成...更新中.... 一.javascipt设计模式分类 设计模式分类有很多标准,最流行的三种如下 1)  creational  --  主要关注对象创建 Creational des ...

随机推荐

  1. 01JavaIO详解_File类

    对程序语言设计者来说,设计一个令人满意的I/O系统,是件极艰难的任务.——摘自Think in java 对java而言,File表示的是文件或目录.但是我们知道文件和目录是不一样的,文件里面存放的是 ...

  2. Datagrid数据导出到excel文件的三种方法

    原文连接: http://www.cnblogs.com/xieduo/articles/606202.html 一.文件保存在服务器,提供下载 方法一:导出到csv文件,存放在服务器端任一路径,然后 ...

  3. VS2010引用App_Code下的类文件问题解决方法

    原文连接:http://blog.csdn.net/zjlovety/article/details/7658528 VS2020中“添加ASP.NET文件夹”里没有App_Code,添加普通文件夹然 ...

  4. C/C++中的结构体

    结构体定义 结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构.   结构体作用 结构体和其他类型基础数据类型一样,例如int类型,char类型 只不过结构体可以做成 ...

  5. IOS开发之——登录加密也许用到的,反转字符串

    - (NSString *)stringByReversed{//    NSMutableString *s = [NSMutableString string];//    for (NSUInt ...

  6. IL指令大全

    IL是.NET框架中中间语言(Intermediate Language)的缩写.使用.NET框架提供的编译器可以直接将源程序编译为.exe或.dll文件,但此时编译出来的程序代码并不是CPU能直接执 ...

  7. 【WEB前端经验之谈】没有速成,只有不断积累。

    2013年8月25日,我人生中的第一份正式工作开始了,第一份工作做的是当时学习的asp.net,用的是C#语言. 到第一家公司上班是公司是做一个OA系统,不过我去的时候大部分都已经完成了,剩下的都是细 ...

  8. android加固签名工具(源码下载)

    背景 每次android加固了都要命令行签名好麻烦,正好之前做了个图标生成工具. 所以改了改,比写批处理还要省事. 原理 其实就是用winform程序调用控制台执行命令,android签名的命令如下 ...

  9. servlet请求转发、包含以及重定向

    请求转发: 方式一: ServletContext对象.getRequestDispatcher(目标资源的URI).forward(request,response); 目标资源的URI " ...

  10. css中的伪类和伪元素

    伪类用单冒号 我们平时熟悉的a:link.a:visited.a:hover和a : active 伪元素用双冒号(为了更好的兼容我们也用单冒号) 常用的:before    :after和 :fir ...