关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » JavaScript »Javascript中的AOP编程

    Javascript中的AOP编程

    2014-09-03 00:00:00 出处:CSDN博客
    分享

    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.

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

    duck

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

    var 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博客上的这个例子:

    /**
    我们都知道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的模式不过如此:

    (function($){

    var _old = $.fn.method;

    $.fn.method = function(arg1,arg2){

    if ( … condition … ) {
    return ….
    } else { // do the default
    return _old.apply(this,arguments);
    }
    };
    })(jQuery);

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

    AOP

    入门

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

    怎么理解切面?

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

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

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

    Class Person
    {
    private int money
    public void pay(price)
    {
    try
    {
    if (checkAuthorize() == true) {
    this.money = this.money – price;
    sendLog();
    }
    }
    catch (Exception e)
    {

    }
    }
    }

    更可怕的是,其他的方法中也要添加相似的代码,这样以来代码的可维护性和可读性便成了很大的问题。我们希望把这些零散但是公共的非业务代码收集起来,更友好的使用和管理他们,这便是切面编程。切面编程在避免修改远代码的基础上实现了代码的复用。就好比把不同的对象横向剖开,关注于内部方法改造。而面向对象编程更关注的是整体的架构设计。

    实现

    在上一节中介绍的duck punch与切面编程类似,都是在改造原方法的同时保证原方法功能。但就像结尾说的一样,直接修改原方法的模式有悖于面向对象最佳实践的原则。

    Javascript可以采用装饰者模式(给原对象添加额外的职责但避免修改原对象)实现AOP编程。注意在这里强调的是实现,我进一步想强调的是,切面编程只是一种思想,而装饰者模式只是实践这种思想的一种手段而已,比如在Java中又可以采用代理模式等。切面编程在Java中发挥的余地更多,也更标准,本想把Java的实现模式也搬来该文中,但不才Java水平有限,对Java的实现不是非常理解。在这里就只展示Javascript的实现。

    AOP中有一些概念需要介绍一下,虽然我们不一定要严格执行

    joint-point:原业务方法; advice:拦截方式 point-cut:拦截方法

    关于这三个概念我们可以串起来可以这么理解:

    当我们使用AOP改造一个原业务方法(joint-point)时,比如加入日志发送功能(point-cut),大家要考虑在什么情况下(advice)发送日志,是在业务方法触发之前还是之后;还是在抛出异常的时候,还是由日志发送是否成功再决定是否执行业务方法。

    比如gihub上的meld这个开源项目,就是一个很典型的AOP类库,我们看看它的API:

    // 假设我们有一个对象myObject, 并且该对象有一个doSomething方法:

    var myObject = {
    doSomething: function(a, b) {
    return a + b;
    }
    };

    // 现在我们想拓展它,在执行那个方法之后打印出刚刚执行的结果:

    var remover = meld.after(myObject, ‘doSomething’, function(result) {
    console.log(‘myObject.doSomething returned: ‘ + result);
    });

    // 试试执行看:

    myObject.doSomething(1, 2); // Logs: “myObject.doSomething returned: 3″

    // 这个时候我们想移除刚刚的修改:

    remover.remove();

    由此可以看出,AOP接口通常需要三个参数,被修改的对象,被修改对象的方法(joint-point),以及触发的时机(adivce),还有触发的动作(point-cut)。上面说了那么多的概念,现在可能要让各位失望了,Javascript的实现原理其实非常简单

    function doAfter(target, method, afterFunc){
    var func = target[method];
    return function(){
    var res = func.apply(this, arguments);
    afterFunc.apply(this, arguments);
    return res;
    };
    }

    当然,假如想看到更完备的解决方案和代码可以参考上面所说的meld项目

    结束语

    这一篇一定让你失望了,代码简单又寥寥无几。该文主要在于介绍有关duck和AOP的这几类思想,我想编程的乐趣不仅仅在于落实在编码上,更在于整个架构的设计。提高代码的可维护性和可拓展性会比高深莫测的代码更重要。

    参考文献:

    How to Fulfill Your Own Feature Request -or- Duck Punching With jQuery! Duck Punching JavaScript – Metaprogramming with Prototype Does JavaScript have the interface type (such as Java’s ‘interface’) AOP技术基础
    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    帝国CMS7.5编辑器上传图片取消宽高的三种方法

    帝国cms如何自动生成缩略图的实现方法

    Windows 12即将到来,将彻底改变人机交互

    帝国CMS 7.5忘记登陆账号密码怎么办?可以phpmyadmin中重置管理员密码

    帝国CMS 7.5 后台编辑器换行,修改回车键br换行为p标签

    Windows 11 版本与 Windows 10比较,新功能一览

    Windows 11激活产品密钥收集及专业版激活方法

    IT头条

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    严重缩水!NVIDIA将推中国特供RTX 5090 DD:只剩24GB显存

    00:17

    无线路由大厂 TP-Link突然大裁员:补偿N+3

    02:39

    Meta 千万美金招募AI高级人才

    00:22

    技术热点

    微软已修复windows 7/windows 8.1媒体中心严重漏洞 用户可下载安

    卸载MySQL数据库,用rpm如何实现

    windows 7中使用网上银行或支付宝支付时总是打不开支付页面

    一致性哈希算法原理设计

    MySQL数字类型中的三种常用种类

    如何解决SQL Server中传入select语句in范围参数

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。