首页 > 网站 > WEB开发 > 正文

聊聊Javascript中的AOP编程

2024-04-27 14:18:22
字体:
来源:转载
供稿:网友

聊聊javascript中的AOP编程

Duck punch

  我们先不谈AOP编程,先从duck punch编程谈起。

  如果你去wikipedia中查找duck punch,你查阅到的应该是monkey patch这个词条。根据解释,Monkey patch这个词来源于 guerrilla patch,意为在运行中悄悄的改变代码,而 guerrilla 这个词与 gorilla 同音,而后者意又与monkey相近(前者为“猩猩”的意思),最后就演变为了monkey patch。

  如果你没有听说过duck punch,但你或许听说过duck typing。举一个通俗的例子,如何辨别一只鸭子:

When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.

  没错,如果我发现有一类动物像鸭子一样叫,像鸭子一样游泳,那么它就是一只鸭子!

  这个检测看上去似乎有一些理所当然和无厘头,但却非常的实用。 并且在编程中可以用来解决一类问题——对于Javascript或者类似的动态语言,如何实现“接口”或者“基类”呢?我们可以完全不用在乎它们的过去如何,我们只关系在使用它们的时候,方法的类型或者参数是否是我们需要的:

123456var quack = someObject.quack;if (typeof quack == "function" && quck.length == arguLength){// This thing can quack}

  扯远了,其实我想表达的是duck punch其实是由duck typing演化而来的:

if it walks like a duck and talks like a duck, it’s a duck, right? So if this duck is not giving you the noise that you want, you’ve got to just punch that duck until it returns what you expect.

  当你想一只鸭子发出驴的叫声怎么办,揍到它发出驴的叫声为止……话说这让我想到一个非常形象的笑话:

为了测试美国、香港、中国大陆三地警察的实力, 联合国将三只兔子放在三个森林中,看三地警察谁先找出兔子。任务:找出兔子。 (中间省略……) 最后是某国警察,只有四个,先打了一天麻将,黄昏时一人拿一警棍进入森林,没五分钟,听到森林里传来一阵动物的惨叫,某国警察一人抽着一根烟有说有笑的出来,后面拖着一只鼻青脸肿的熊,熊奄奄一息的说到:“不要再打了,我就是兔子……”

  虽然duck punch有些暴力,但不失为一个有效的方法。落实到代码上来说就是让原有的代码兼容我们需要的功能。比如Paul Irish博客上的这个例子:

1234567891011121314151617181920212223242526/**我们都知道jQuery的`$.CSS`方法可以通过使用颜色的名称给元素进行颜色赋值。但jQuery内置的颜色并非是那么丰富,如果我们想添加我们自定义的颜色名称应该怎么办?比如我们想添加`Burnt Sienna`这个颜色*/(function($){// 把原方法暂存起来:var _oldcss = $.fn.css;// 重写原方法:$.fn.css = function(PRop,value){// 把自定义的颜色写进分支判断里,特殊情况特殊处理if (/^background-?color$/i.test(prop) && value.toLowerCase() === 'burnt sienna') {return _oldcss.call(this,prop,'#EA7E5D');// 一般情况一般处理,调用原方法} else {return _oldcss.apply(this,arguments);}};})(jQuery);// 使用方法:jQuery(document.body).css('backgroundColor','burnt sienna')

  同时可以推倒出duck punch的模式不过如此:

12345678910111213(function($){var _old = $.fn.method;$.fn.method = function(arg1,arg2){if ( ... condition ... ) {return ....} else { // do the defaultreturn _old.apply(this,arguments);}};})(jQuery);

  但是这么做有一个问题:需要修改原方法。这违背了“开放-封闭”原则,本应对拓展开放,对修改关闭。怎么解决这个问题呢?使用AOP编程。

 AOP

  入门

  AOP全称为aspect-oriented programming,很明显这是相对于Object-oriented programming而言。Aspect可以翻译为“切面”或者“侧面”,所以AOP也就是面向切面编程。

  怎么理解切面?

  在面向对象编程中,我们定义的类通常是领域模型,它的拥有的方法通常是和纯粹的业务逻辑相关。比如:

12345678Class Person{private int money;public void pay(int price){this.money = this.money - price; }}

  但通常实际情况会更复杂,比如我们需要在付款的pay方法中加入授权检测,或者用于统计的日志发送,甚至容错代码。于是代码会变成这样:

123456789101112131415161718Class Person{private int moneypublic void pay(price){try{
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表