设计模式之面向切面编程AOP

更新日期: 2019-03-09阅读: 2.2k标签: AOP

动态的将代码切入到指定的方法、指定位置上的编程思想就是面向切面的编程。代码只有两种,一种是逻辑代码、另一种是非逻辑代码。逻辑代码就是实现功能的核心代码,非逻辑代码就是处理琐碎事务的代码,比如说获取连接和关闭连接,事务开始,事务提交还有log等任何与核心逻辑无关的功能。

AOP(面向切面编程)的主要作用是把一些跟核心业务逻辑模块无关的功能抽离出来,这些跟业务逻辑无关的功能通常包括日志统计、安全控制、异常处理等。把这些功能抽离出来之后, 再通过“动态织入”的方式掺入业务逻辑模块中。 


为什么要用面向切面编程AOP

假如说DB的相关开发,我们需要每次在相关功能之前需要连接数据库,在每次在功能之后要关闭连接。

每次开发的时候都需要再写一遍这些非逻辑代码,而AOP的思想就是将这些非逻辑代码提取出来,我们只考虑逻辑代码就行了。

把框框设计好,这里写前面的连接数据库,这里写逻辑,这里写后面的关闭连接。


面向切面编程的例子

css就是最简单的例子,html页面就是从上到下渲染的,遇到一个CSS就加载一个.

a some html tag
a.css
b some html tag
b.css

一开始,会加载a some html tag ,然后会加载a.css 然后,会加载b some html tag ,最后加载 b.css。


AOP能给我们带来什么好处?

AOP的好处首先是可以保持业务逻辑模块的纯净和高内聚性,其次是可以很方便地复用日志统计等功能模块。 

 

JavaScript实现AOP的思路?

通常,在 JavaScript 中实现 AOP,都是指把一个函数“动态织入”到另外一个函数之中,具体的实现技术有很多,下面我用扩展 Function.prototype 来做到这一点。请看下面代码:

Function.prototype.before = function (beforefn) {
       var _self = this;    //保存原函数引用
       return function () { //返回包含了原函数和新函数的"代理函数"
           beforefn.apply(this, arguments); //执行新函数,修正this
           return _self.apply(this, arguments); //执行原函数
       }
   };

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

   var func = function () {
       console.log("2")
   }

   func = func.before(function () {
       console.log("1");
   }).after(function () {
       console.log("3");
   } )

   func();

我把负责打印数字1和打印数字3的两个函数通过AOP的方式动态植入func函数。通过执行上面的代码,我们看到控制台顺利地返回了执行结果1、2、3。

这种使用AOP的方式来给函数添加职责,也是JavaScript语言中的一种非常特别的巧妙的装饰者模式实现,下面我们来试试Function.prototype.before的威力,请看下面代码:

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

    document.getElementById = document.getElementById.before(function(){ alert (1);
    });
    var button = document.getElementById( 'button' );

我们给document.getElementById()做了一些装饰,以后我们每次调用这个方法之前都会先执行alert("1")这条语句,但是请注意我们这条语句并不是写在了document.getElementById()这个方法的源码中,而只是在他的外部给他加了装饰,这样带来好处就是我们可以在不改变原方法的源码的情况下为他添加一些新的行为。 


链接: https://www.fly63.com/article/detial/2270

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!