一、装饰者模式定义

装饰者模式可以动态地给某个对象添加一些额外的职责,而不会影响从这个类中派生的其他对象。这种为对象动态添加职责的方式就称为装饰者模式。装饰者对象和它所装饰的对象拥有一致的接口,对于用户来说是透明的。

和java等语言不同的是,java的装饰器模式是给对象动态添加职责,javascript中,给对象添加职责的能力是与生俱来的,更侧重于给函数动态添加职责。

二、java中的装饰者模式实现

package com.bobo.shejimoshi.derector;

public class Plane {
public void fire(){
System.out.println("发射普通子弹");
}
}
package com.bobo.shejimoshi.derector;

public class MissileDecorator {
private Plane plane;
public MissileDecorator(Plane plane){
this.plane=plane; } public void fire(){
plane.fire();
System.out.println("发射导弹");
}
}

可见在java等传统语言中,给对象动态增加职责的方式,并没有真正地改动对象自身,而是将对象放入另一个对象之中,这些对象都具有相同的对外接口。

三、javascript中的装饰者模式实现

3.1为javascript对象添加职责

在javascript中,给对象添加职责是与生俱来的本领。同样是上面的例子,在javascript中可以这么实现:

//装饰者模式
var plane={
fire:function(){
console.log("发射普通子弹");
},
}; var missileDecorator=function(){
console.log("发射导弹");
}; var fire1=plane.fire;
plane.fire=function(){
fire1();
missileDecorator();
}; plane.fire();

3.2为javascript函数添加职责

为函数添加一些功能,在java等语言中貌似只能直接改写该函数,这显然违反了开放—封闭原则;

如果不想更改原函数,可以像上面的例子,通过保存原函数引用的方式来改写某个函数,这种方式一种是需要借助中间变量保存原函数的引用,此外还会遇到this劫持的问题。

因此,比较好的方式是利用AOP来进行函数装饰。

Function.prototype.before

Function.prototype.before=function(beforeFn){
var _self=this;//保存原函数的引用
return function(){
beforeFn.apply(this,arguments);
return _self.apply(this,arguments);
};
}; document.getElementById=document.getElementById.before(function(){
alert();
}); var sel=document.getElementById('colorSelect');

如果想根据上一个函数的执行结果决定函数是否执行,甚至还可以这样写Function.prototype.before

Function.prototype.before=function(beforeFn){
var _self=this;
return function(){
if(beforeFn.apply(this,arguments)!==false){
_self.apply(this,arguments);
} };
};

使用这种方法还可以动态改变函数的参数:

    var func=function(param){
console.log(param);
};
func=func.before(function(param){
param.b='b';
});
func({'a':'a'});//输出 'a':a,'b':b

Function.prototype.after

Function.prototype.after=function(afterFn){
var _self=this;
return function(){
var ret=_self.apply(this,arguments);
afterFn.apply(this,arguments);
return ret;
};
};

javascript设计模式学习之十五——装饰者模式的更多相关文章

  1. javascript设计模式学习之十二——享元模式

    一.享元模式的定义及使用场景 享元模式是为了解决性能问题而诞生的设计模式,这和大部分设计模式为了提高程序复用性的原因不太一样,如果系统中因为创建了大量类似对象而导致内存占用过高,享元模式就非常有用了. ...

  2. javascript设计模式学习之十四——中介者模式

    一.中介者模式的定义和应用场景 中介者模式的作用在于解除对象之间的紧耦合关系,增加一个中介者之后,所有对象都通过中介者来通信,而不是互相引用,当一个对象发生变化的时候,仅需要通知中介者即可.从而将网状 ...

  3. Java 设计模式系列(十五)迭代器模式(Iterator)

    Java 设计模式系列(十五)迭代器模式(Iterator) 迭代器模式又叫游标(Cursor)模式,是对象的行为模式.迭代子模式可以顺序地访问一个聚集中的元素而不必暴露聚集的内部表象(interna ...

  4. javascript基础学习(十五)

    javascript之cookie 学习要点: cookie介绍 创建与获取cookie cookie的编码 cookie的生存期 cookie的路径 cookie的domain cookie的sec ...

  5. javascript设计模式学习之十六——状态模式

    一.状态模式的定义 状态模式的关键是区分事务内部和外部的状态,事务内部状态改变往往会带来事务的行为改变. 状态模式中有意思的一点是,一般我们谈到封装,都是优先封装对象的行为,而非对象的状态.但在状态模 ...

  6. javascript设计模式学习之十——组合模式

    一.组合模式定义及使用场景 组合模式将对象组合成树形结构,用以表示“部分—整体”的层次结构,除了用来表示树形结构之外,组合模式还可以利用对象的多态性表现,使得用户对单个对象和组合对象的使用具有一致性. ...

  7. 设计模式学习总结(五)创建者模式(Builder)

    创建者模式,主要针对某些产品有类似的生产步骤,且有需要有先后顺序的进行各个部件的生成. 一.示例展示: 通过学习及总结,以下是我完成的创建者模式的示例: 1.创建产品类:Laptop public c ...

  8. JavaScript中常见的十五种设计模式

    在程序设计中有很多实用的设计模式,而其中大部分语言的实现都是基于“类”. 在JavaScript中并没有类这种概念,JS中的函数属于一等对象,在JS中定义一个对象非常简单(var obj = {}), ...

  9. 【转】设计模式 ( 十五 ) 中介者模式Mediator(对象行为型)

    设计模式 ( 十五 ) 中介者模式Mediator(对象行为型) 1.概述 在面向对象的软件设计与开发过程中,根据"单一职责原则",我们应该尽量将对象细化,使其只负责或呈现单一的职 ...

随机推荐

  1. NBOJv2 1034 Salary Inequity(DFS序+线段树区间更新区间(最值)查询)

    Problem 1034: Salary Inequity Time Limits:  10000 MS   Memory Limits:  200000 KB 64-bit interger IO ...

  2. php处理数组函数大全

    PHP:指示支持该函数的最早的 PHP 版本. 函数 描述 PHP array() 创建数组. 3 array_change_key_case() 返回其键均为大写或小写的数组. 4 array_ch ...

  3. [ZZ] Understanding 3D rendering step by step with 3DMark11 - BeHardware >> Graphics cards

    http://www.behardware.com/art/lire/845/ --> Understanding 3D rendering step by step with 3DMark11 ...

  4. Javascript 笔记与总结(1-1)作用域

    以语言的角度学习 Js 的底层原理(与 DOM 无关):① 作用域链 ② 词法分析 ③ 闭包 ④ 面向对象(原型链) ① 作用域链 例1 <script> var c = 5; funct ...

  5. mysql 关于日期时间的字段类型

    mysql日期和时间类型 mysql有5种表示时间值的日期和时间类型,分别为.DATE,TIME,YEAR,DATETIME,TIMESTAMP. TIMESTAMP类型有专有的自动更新特性, TIM ...

  6. json解析json字符串时候,数组必须对应jsonObjectArray,不能对应JsonObject。否则会解析错误。

    json第三方解析json字符串时候,json数组必须对应jsonObjectArray,不能对应JsonObject.->只要是[]开头的都是json数组字符串,就要用jsonArray解析 ...

  7. Apache服务器代理与缓存

    Apache服务器代理与缓存 1.代理  正向代理:             反向代理:   mod_proxy模块 apache实现代理和网关的关键模块.加载mod_proxy模块:LoadModu ...

  8. Python For Data Analysis -- IPython

    IPython Basics 首先比一般的python shell更方便一些 比如某些数据结构的pretty-printed,比如字典 更方便的,整段代码的copy,执行 并且可以兼容部分system ...

  9. OpenGL完全教程 第一章 初始化OpenGL

    第一章 初始化OpenGL 无论是什么东西,要使用它,就必须对它进行初始化.如果你之前使用过GDI,你应该也多多少少了解到GDI在绘制图形之前要为之创建渲染环境.OpenGL也一样.本章给出的代码,大 ...

  10. spring-3-mvc-hello-world-example

    http://www.mkyong.com/spring3/spring-3-mvc-hello-world-example/