介绍

装饰者提供比继承更有弹性的替代方案。 装饰者用用于包装同接口的对象,不仅允许你向方法添加行为,而且还可以将方法设置成原始对象调用(例如装饰者的构造函数)。

装饰者用于通过重载方法的形式添加新功能,该模式可以在被装饰者前面或者后面加上自己的行为以达到特定的目的。

正文

那么装饰者模式有什么好处呢?前面说了,装饰者是一种实现继承的替代方案。当脚本运行时,在子类中增加行为会影响原有类所有的实例,而装饰者却不然。取而代之的是它能给不同对象各自添加新行为。如下代码所示:

//需要装饰的类(函数)
function Macbook() {
this.cost = function () {
return 1000;
};
} function Memory(macbook) {
this.cost = function () {
return macbook.cost() + 75;
};
} function BlurayDrive(macbook) {
this.cost = function () {
return macbook.cost() + 300;
};
} function Insurance(macbook) {
this.cost = function () {
return macbook.cost() + 250;
};
} // 用法
var myMacbook = new Insurance(new BlurayDrive(new Memory(new Macbook())));
console.log(myMacbook.cost()); 下面是另一个实例,当我们在装饰者对象上调用performTask时,它不仅具有一些装饰者的行为,同时也调用了下层对象的performTask函数。 function ConcreteClass() {
this.performTask = function () {
this.preTask();
console.log('doing something');
this.postTask();
};
} function AbstractDecorator(decorated) {
this.performTask = function () {
decorated.performTask();
};
} function ConcreteDecoratorClass(decorated) {
this.base = AbstractDecorator;
this.base(decorated); decorated.preTask = function () {
console.log('pre-calling..');
}; decorated.postTask = function () {
console.log('post-calling..');
}; } var concrete = new ConcreteClass();
var decorator1 = new ConcreteDecoratorClass(concrete);
var decorator2 = new ConcreteDecoratorClass(decorator1);
decorator2.performTask(); 再来一个彻底的例子: var tree = {};
tree.decorate = function () {
console.log('Make sure the tree won\'t fall');
}; tree.getDecorator = function (deco) {
tree[deco].prototype = this;
return new tree[deco];
}; tree.RedBalls = function () {
this.decorate = function () {
this.RedBalls.prototype.decorate(); // 第7步:先执行原型(这时候是Angel了)的decorate方法
console.log('Put on some red balls'); // 第8步 再输出 red
// 将这2步作为RedBalls的decorate方法
}
}; tree.BlueBalls = function () {
this.decorate = function () {
this.BlueBalls.prototype.decorate(); // 第1步:先执行原型的decorate方法,也就是tree.decorate()
console.log('Add blue balls'); // 第2步 再输出blue
// 将这2步作为BlueBalls的decorate方法
}
}; tree.Angel = function () {
this.decorate = function () {
this.Angel.prototype.decorate(); // 第4步:先执行原型(这时候是BlueBalls了)的decorate方法
console.log('An angel on the top'); // 第5步 再输出angel
// 将这2步作为Angel的decorate方法
}
}; tree = tree.getDecorator('BlueBalls'); // 第3步:将BlueBalls对象赋给tree,这时候父原型里的getDecorator依然可用
tree = tree.getDecorator('Angel'); // 第6步:将Angel对象赋给tree,这时候父原型的父原型里的getDecorator依然可用
tree = tree.getDecorator('RedBalls'); // 第9步:将RedBalls对象赋给tree tree.decorate(); // 第10步:执行RedBalls对象的decorate方法 总结 装饰者模式是为已有功能动态地添加更多功能的一种方式,把每个要装饰的功能放在单独的函数里,然后用该函数包装所要装饰的已有函数对象,因此,当需要执行特殊行为的时候,调用代码就可以根据需要有选择地、按顺序地使用装饰功能来包装对象。优点是把类(函数)的核心职责和装饰功能区分开了。 同步与推荐 本文已同步至目录索引:深入理解JavaScript系列 深入理解JavaScript系列文章,包括了原创,翻译,转载等各类型的文章,如果对你有用,请推荐支持一把,给大叔写作的动力。

深入理解JavaScript系列(29):设计模式之装饰者模式的更多相关文章

  1. 深入理解JavaScript系列(50):Function模式(下篇)

    介绍 本篇我们介绍的一些模式称为初始化模式和性能模式,主要是用在初始化以及提高性能方面,一些模式之前已经提到过,这里只是做一下总结. 立即执行的函数 在本系列第4篇的<立即调用的函数表达式> ...

  2. 深入理解JavaScript系列(49):Function模式(上篇)

    介绍 本篇主要是介绍Function方面使用的一些技巧(上篇),利用Function特性可以编写出很多非常有意思的代码,本篇主要包括:回调模式.配置对象.返回函数.分布程序.柯里化(Currying) ...

  3. 深入理解JavaScript系列

    转自http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html 深入理解JavaScript系列(1):编写高质量JavaScript代码 ...

  4. 深入理解JavaScript系列(转自汤姆大叔)

    深入理解JavaScript系列文章,包括了原创,翻译,转载,整理等各类型文章,如果对你有用,请推荐支持一把,给大叔写作的动力. 深入理解JavaScript系列(1):编写高质量JavaScript ...

  5. [转]深入理解JavaScript系列

    文章转自:汤姆大叔-深入理解JavaScript系列文章 深入理解JavaScript系列文章,包括了原创,翻译,转载,整理等各类型文章,如果对你有用,请推荐支持一把,给大叔写作的动力. 深入理解Ja ...

  6. [转载]深入理解JavaScript系列 --汤姆大叔

    深入理解JavaScript系列文章,包括了原创,翻译,转载,整理等各类型文章,如果对你有用,请推荐支持一把,给大叔写作的动力. 深入理解JavaScript系列(1):编写高质量JavaScript ...

  7. 深入理解JavaScript系列(转载)

    深入理解JavaScript系列 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点 深入理解JavaScript系列(2):揭秘命名函数表达式 深入理解JavaSc ...

  8. 深入理解JavaScript系列(39):设计模式之适配器模式

    介绍 适配器模式(Adapter)是将一个类(对象)的接口(方法或属性)转化成客户希望的另外一个接口(方法或属性),适配器模式使得原本由于接口不兼容而不能一起工作的那些类(对象)可以一些工作.速成包装 ...

  9. 深入理解JavaScript系列(40):设计模式之组合模式

    介绍 组合模式(Composite)将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性. 常见的场景有asp.net里的控件机制(即control ...

随机推荐

  1. 搭建linux虚拟机

    一.VMware 9 安装CentOS 7 -> 创建新虚拟机, 选择稍后安装操作系统    -> 选择Linux系统Centos 64位    -> 填写虚拟机名称, 选择虚拟机安 ...

  2. 《C#多线程编程实战》2.9 ReaderWirterLockSlim

    可以多线程进行读写操作. 比如书上的示例代码是三个线程进行读取,两个线程进行写入工作. 如果 用之前学过的也不是不可以用,但是用的有些多. 所有ReaderWirterLockSlim专门为此而来. ...

  3. Response Assertion(响应断言)

    响应断言可以让你添加匹配字符串来匹配请求和响应的各个字符串. 匹配字符串可以是1.Contains和Matches正则表达式:2.Equals和SubString文本类型,大小写敏感. Apply t ...

  4. 【转】右键的 在 vs 中打开 怎么去掉

    源地址:https://blog.csdn.net/weicaijiang/article/details/78818522 HKEY_CLASSES_ROOT\Directory\backgroun ...

  5. c++多线程基础1(thread)

    std::thread 在 <thread> 头文件中声明,因此使用 std::thread 时需要包含 <thread> 头文件. thread 构造函数: default ...

  6. 【bzoj4709】[Jsoi2011]柠檬 决策单调性+dp

    Description Flute 很喜欢柠檬.它准备了一串用树枝串起来的贝壳,打算用一种魔法把贝壳变成柠檬.贝壳一共有 N (1 ≤ N ≤ 100,000) 只,按顺序串在树枝上.为了方便,我们从 ...

  7. [转]Why you shouldn't use set (and what you should use instead)

    Why you shouldn't use set (and what you should use instead) --- stl::set和sorted ector对比Matt Austern ...

  8. IK分词器原理与源码分析

    原文:http://3dobe.com/archives/44/ 引言 做搜索技术的不可能不接触分词器.个人认为为什么搜索引擎无法被数据库所替代的原因主要有两点,一个是在数据量比较大的时候,搜索引擎的 ...

  9. Dancing Links算法(舞蹈链)

    原文链接:跳跃的舞者,舞蹈链(Dancing Links)算法——求解精确覆盖问题 作者:万仓一黍 出处:http://grenet.cnblogs.com/ 本文版权归作者和博客园共有,欢迎转载,但 ...

  10. (WIN7)delphi7运行关闭出现cannot creat file"C:\program file\borland\delphi7\bin\initcc32.exe拒绝访问

    1. 程序右键,以管理权限运行.2. 将Delphi7目录只读取消.WIN7以上的操作系统正常运行程序不是以管理员方式运行的