javascript装饰器模式

众所周知装饰器模式用于给对象在运行期间动态的增加某个功能,职责等。相较通过继承的方式来扩充对象的功能,装饰器显得更加灵活,首先,我们可以动态给对象选定某个装饰器,而不用hardcore继承对象来实现某个功能点。其次:继承的方式可能会导致子类繁多,仅仅为了增加某一个单一的功能点,显得有些多余了。

装饰器经典实现

首先来看看传统的decorator的实现吧!假设现有一类叫Person 的对象,该对象有个speak 方法。开始的时候Person 的对象只会说中文,现在我要让他说英文,那么可以这么做:

var Person = function(name) {
    this.name = name;
};

Person.prototype.speak = function() {
    console.log('你好!');
};

var SpeakEnglish = function(person) {
    this.person = person;       
};

SpeakEnglish.prototype.speak = function() {
    this.speak();
    console.log('hello!');
};

var SpeakJapanese = function(person) {
    this.person = person;       
};

SpeakJapanese.prototype.speak = function() {
    this.speak();
    console.log('こんにちは!');
};

var lufy = new Person('lufy');
var engLufy = new SpeakEnglish(lufy);
var japanLufy = new SpeakJapanese(engLufy);
japanLufy.speak();

通过包装对象的方式给原对象增加新的功能,而不会影响原对象的同类对象。通过上面的方式路飞现在可以说3个国家的语言了。

javascript装饰函数

对于javascript这类支持函数式编程的语言,我们要装饰对象的某个方法其实也可以更加简便,譬如说,通常我们写前端页面处理的时候需要监听窗口的onload 事件,但是同样一个onload 需要被多个地方监听,可以这么做:

var attachOnloadHandle = function(doit) {
    if(typeof window.onload !== 'function') {
        window.onload = doit;
    }
    else {
        var func = window.onload;
        window.onload = function() {
            func();
            doit();
        };
    }
};

函数实现比较简单,但也算实用吧!

装饰器模式与AOP

AOP是面向切面编程的简写。其语意为把一些与核心业务模块无关的功能剥离出来,把整个系统划分为更小的粒度。在完成这些子模块的设计编码后再逐步包装起来完成更大的功能。

javascript动态装饰函数

通过前面的例子我们看到所谓装饰无非是在执行某个功能之前执行一些前置或后置处理,提供两个更加通用的接口:

Function.prototype.before = function(beforfunc) {
    var self = this;
    return function() {
        beforfunc.apply(this, arguments);
        self.apply(this, arguments);
    };
};

Function.prototype.after = function(afterfunc) {
    var self = this;
    return function() {
        self.apply(this, arguments);
        afterfunc.apply(this, arguments);
    };
};

试一试:

var func = function() {
    console.log('hello');   
};
func.before(function() {
    console.log('你好');
}).after(function() {
    console.log('こんにちは!');
});

考虑到安全方面的因素,我们在给微信服务器发送一些请求的时候都需要带上accessToken 有些操作不需要带这个参数,通过AOP函数包装我们可以这样来做:

var getToken = function(cb) {
    //...   
};
var preRequest = function(doit, params) {
    var self = this;
    getToken(function(err, token) {
        if(err) {
            //xxx
            return;
        }
        self.token = token;
        doit.apply(self, params);
    });
};

var make = function(host, name, func) {
    host[name] = function() {
        this.preRequest(this['_' + name], arguments);
    };
    host['_' + name] = func;
};

//获取卡券
make(exports, 'getCard', function(cardId, cb) {
    var url = 'http://www.wechat.com/xxxx' + this.token;
    //...
});
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值