介绍

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

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

正文

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

//需要装饰的类(函数)
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. 201621123012 《java程序设计》第3周学习总结

    1. 本章学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词 答:关键词:继承 多态 抽象类 abstract 覆盖 object siper 1.2 尝试使用思维导图将这些关键词组织起来. ...

  2. Python实现——决策树(部分函数/连续数据)

    由于上一例的实现中只针对了离散数据,为了扩充处理范围,我实现了一下对线性数据的简单处理,在其中我选择用中位数作为指标,平均数.众数等等其他数据在我看来异曲同工,最终也都会有较相似的结构. 求连续数据的 ...

  3. Python中实现简单的插件框架

    在系统设计中,经常我们希望设计一套插件机制,在不修改程序主体情况下,动态去加载附能. 我设想的插件系统: 1.通过类来实现 2.自动查找和导入 我们假设需要实现一个简单的插件系统,插件可以接收一个参数 ...

  4. 自动判断PC端、手机端跳往不同的域名JS实现代码

    输入相同域名,在pc端和移动端会出现不同的页面效果,一种是用栅格系统实现自适应, 更多的是设计两套不同的模板和两个二级域名或者一个主域名和一个二级域名(就是有区别就可以了); js代码判断浏览器的用户 ...

  5. swift pod 第三方库异常的处理

    Xcode8—Swift开发使用Cocoapods引入第三方库异常处理方法 参考:  http://www.jianshu.com/p/23f13be525a0 //podfile文件如下 platf ...

  6. C++_类入门5-智能指针模板类

    智能指针是行为类似于指针的类对象,但这种对象还有其他功能. 本节介绍三个可帮助管理动态内存分配的智能指针模板(auto_ptr.unique_ptr和shared_ptr). void remodel ...

  7. LeetCode记录之7——Reverse Integer

    Reverse digits of an integer. Example1: x = 123, return 321Example2: x = -123, return -321 Note:The ...

  8. 对于position:relative,absolute,fixed的见解:

    1.switch--fixed,div脱离父元素,top,left,right,bottom都是相对于body,自己原来的位置不存在,即不占父元素位置了 2.switch--relative,div相 ...

  9. flume将数据发送到kafka、hdfs、hive、http、netcat等模式的使用总结

    1.source为http模式,sink为logger模式,将数据在控制台打印出来. conf配置文件如下: # Name the components on this agent a1.source ...

  10. JavaScript 精简笔记

    JavaScript 精简笔记,摘自 廖雪峰的官方网站. [From] https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51 ...