Fork me on GitHub

装饰者模式


装饰者模式:给对象动态地增加职责。跟继承相比,装饰者是一种更轻便灵活的做法,是一种“即用即付”的方式。

js的装饰者

假设我们在编写一个飞机大战游戏,这个飞机可以升级,发射导弹,发射原子弹

var plane = {
    fire: function() {
        console.log('发射普通子弹');
    }
};
var missileDecorator = function() {
    console.log('发射导弹');
};
var atomDecorator = function() {
    console.log('发射原子弹');
};
var fire1 = plane.fire;
plane.fire = function() {
    fire1();
    missileDecorator();
};

var fire2 = plane.fire;
plane.fire = function() {
    fire2();
    atomDecorator();
};
plane.fire(); //"发射普通子弹""发射导弹""发射原子弹"

用AOP装饰函数

首先给出Function.prototype.before方法和Function.prototype.after方法

Function.prototype.before = function (beforefn) {
  var __self = this; //保存原函数的引用
  return function() {  //返回包含了原函数和新函数的代理函数
    beforefn.apply(this, arguments); //执行新函数,且保证this不被劫持,新函数接受的参数也会原封不动的传入原函数,新函数在原函数之前执行
    return __self.apply(this, arguments); //执行原函数并返回原函数的执行结果,并保证this不被劫持
  };
};
Function.prototype.after = function (afterfn) {
  var __self = this; 
  return function() {
    var ret = __self.apply(this, arguments); 
    afterfn.apply(this, arguments); 
    return ret;
  };
};

需求:
页面中有个按钮,点击会弹出登录浮层,与此同时要进行数据上报, 这时候我们最好去分离业务代码和数据统计代码,以便维护。

var showLogin = function() {
    console.log('打开登陆浮层');
    log(this.getAttribute('tag'));
}
var log = function(tag) {
    console.log('上报标签为:' + tag);
}
document,getElementById('button').onclick = showLogin;

以上,showLogin函数既要负责打开登录浮层,又要负责数据上报,这是两个层面的功能,却被耦合在一个函数里,我们做点分离..

var showLogin = function() {
    console.log('打开登陆浮层');
}
var log = function(tag) {
    console.log('上报标签为:' + tag);
}

showLogin = showLogin.after(log); //打开登录浮层之后上报数据
document,getElementById('button').onclick = showLogin;

装饰者模式和代理模式

代理模式和装饰者模式两种都描述了怎样为对象提供一定程度上的间接引用,他们的实现部分都保留了对另外一个对象的引用,并且向那个对象发送请求。
代理模式和装饰者模式最重要的区别在于他们的意图和设计目的。代理模式的目的是当直接访问本体不方便或者不符合需求时,为这个本体提供一个替代者。代理模式强调一种关系,这种关系一开始就以确定且通常只有一层代理-本体的引用。而装饰者模式的作用是为对象的动态加入行为,一开始不能确定对象的全部行为,通常装饰者模式会形成一条长长的链。

我知道是不会有人点的,但万一有人想不开呢?