• 面向切面编程(AOP)


    面向切面编程(Aspect-Oriented Programming/AOP) 解决的是 cross-cutting concerns 问题。比如同一段代码在不同模块中重复,又不能简单地通过抽取公共方法的方式来达到重构,比如日志与参数校验。

    以下是展示这一编程思想的一段伪代码:

    function mainProgram()
    { 
       var x =  foo();
       doSomethingWith(x);
       return x;
    }
    

    aspect logging
    {
    before (mainProgram is called):
    {
    log.Write("entering mainProgram");
    }

    after (mainProgram is called):
    { 
       log.Write(  "exiting mainProgram with return value of "
                  + mainProgram.returnValue);
    }
    

    }

    aspect verification
    {
    before (doSomethingWith is called):
    {
    if (doSomethingWith.arguments[0] == null)
    {
    throw NullArgumentException();
    }

       if (!doSomethingWith.caller.isAuthenticated)
       { 
          throw Securityexception();
       }
    }
    

    }

    代码进行编译转换后实际成为这样子:

    function mainProgram()
    { 
       log.Write("entering mainProgram");
    

    var x = foo();

    if (x == null) throw NullArgumentException();
    if (!mainProgramIsAuthenticated()) throw Securityexception();
    doSomethingWith(x);

    log.Write("exiting mainProgram with return value of "+ x);
    return x;
    }

    与 Mixin 的差别

    Mixin 中代码与宿主无关,可向宿主添加做生意多的功能。装饰器是侵入式的,将宿主进行代理,对外提供的接口不变,可在相应逻辑运行前后进行拦截操作。

    装饰器

    装饰器(decorator pattern)可认为是一种面向切面的编程。一个装饰器可运用于类(class)属性(property),方法(method)以及参数等(parameter)。加上装饰器后,可用于对目标对象的日志处理,权限检查等与业务无关的操作。

    JavaScript 中的实现

    装饰器如其如,类似于给方法添加一个修饰,具体的功能在装饰器中实现,所有应用了该装饰器的方法都会带上相应的功能。

    主流强类型语言比如 Java,C# 中装饰器由来已久,但 JavaScript 其还处于 stage 2 proposal 阶段。不过可通过 TypeScript 来使用,编译选项中开启 experimentalDecorators 参数。

    {
        "compilerOptions": {
            "experimentalDecorators": true
        }
    }

    装饰器运用最为典型的是 Angular。其整体框架大量使用装饰器来定义各组件模块,同时控制相应组件及模块的行为。

    @Component({
      selector: 'example-component',
      template: '<div>Woo a component!</div>',
    })
    export class ExampleComponent {
      constructor() {
        console.log('Hey I am a component!');
      }
    }

    其他应用场景比如将路由的定义使用装饰器写在 Controller 上,参见 midway 框架 - 路由装饰器

    import { provide, controller, inject, get } from 'midway';
    

    @provide()
    @controller('/user')
    export class UserController {

    @inject('userService')
    service: IUserService;

    @get('/:id')
    async getUser(ctx): Promise<void> {
    const id: number = ctx.params.id;
    const user: IUserResult = await this.service.getUser({id});
    ctx.body = {success: true, message: 'OK', data: user};
    }
    }

    相关资源

  • 相关阅读:
    POJ2686 Traveling by Stagecoach(状压DP+SPFA)
    POJ3250 Bad Hair Day(单调栈)
    POJ3493 Largest Submatrix of All 1’s(单调栈)
    UVA 10160 Servicing Stations(状态压缩+迭代加深)
    POJ 2187 Beauty Contest
    HDU 6017 Girls Love 233(多态继承DP)
    POJ 2932 Coneology(扫描线)
    POJ 1127 Jack Straws (计算几何)
    挑战程序设计竞赛 3.5 借助水流解决问题的网络流
    AOJ 2230 How to Create a Good Game(费用流)
  • 原文地址:https://www.cnblogs.com/Wayou/p/aspect_oriented_programming.html
Copyright © 2020-2023  润新知