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

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. 使用EXISTS语句注意点

    1.使用EXISTS语句,其目标列一般用“*”,因为带EXISTS的子查询只返回真值或假值,给出列名无实际意义. 2.使用EXISTS语句一定要注意上下两个表之间要建立联系. 例如,查询所有选修了1号 ...

  2. 07Mybatis_入门程序——根据前面的做的两个查询联系,做一些小的总结

    总结如下: 1.parameterType和resultType 在映射文件中通过parameterType指定输入 参数的类型. 在映射文件中通过resultType指定输出结果的类型. 例如: & ...

  3. [资料收集]MySQL在线DDL工具pt-online-schema-change

    MySQL在线DDL工具pt-online-schema-change pt-online-schema-change使用说明(未完待续) 官网

  4. 前端开发工程师:网易web前端课程,价值1499元【无水印版】

    这套网上的朋友购买分享给我的,特此分享~ 让大家都受益 早日成为强大的web前端开发工程师!!赶紧回复下载吧 下载地址:http://fu83.cn/thread-172-1-1.html

  5. ios 指南针

    指南针图片  IBOutlet UIImageView *compassView 1 #import "ViewController.h" #import <CoreLoca ...

  6. [CareerCup] 3.7 Adopt Animal 领养动物

    3.7 An animal shelter holds only dogs and cats, and operates on a strictly "first in, first out ...

  7. Thrift搭建分布式微服务(二)

    第二篇 连接池  连接池配置,请前往Thrift搭建分布式微服务(一)  下面要介绍的其实不是单一的连接池,应该说是连接池集合.因为它要管理多个Tcp Socket连接节点,每个服务节点都有设置了自己 ...

  8. asp.net下载文件几种方式

    测试时我以字符流的形式下载文件,可行,前几个仅作参考 protected void Button1_Click(object sender, EventArgs e)  {  /*  微软为Respo ...

  9. linux之条件判断

    一.文件类型比较 判断一个文件是否存在(注意:中括号表示判断,其两边必须有空格) 二.文件权限判断 判断是否有可执行权限(这里是不区分用户的,只要该文件能执行就返回0) 3.整数比较 判断两个数是否相 ...

  10. 14.C#属性访问器、命名空间、pragma指令(七章7.3-7.5)

    看到一些零星的知识片,今天就用自己的理解说明下,也是因为太简单了,一下就过的,也是我们日常开发中常用.留下一个脚印,当书不在手上的,也能翻出来看看.说下属性访问器.命名空间和pragma指令. 属性访 ...