OOP和AOP区别

4 阅读3分钟

1. 是什么(What)—— 本质与定义的区别

  • 面向对象编程(OOP):

    • 本质: 是一种纵向的模块化架构。
    • 定义: 它将现实世界中的事物抽象为“对象”,通过**类(Class)**来组织代码。它的核心是将数据(属性)和行为(方法)封装在一起。
    • 形象理解: 像是在造零件。如果你要造一辆车,你会定义发动机类、轮胎类。这是一种从上到下的、树状的逻辑结构。
  • 面向切面编程(AOP):

    • 本质: 是一种横向的模块化架构。
    • 定义: 它将那些散落在各个业务模块中的公共功能(如日志、安全、事务、异常处理)抽取出来,形成一个独立的“切面”。
    • 形象理解: 像是在加滤镜。不管你是发动机还是轮胎,只要你运行,我都要在你的运行前后“横切”一刀,记录一下运行时间。

2. 为什么(Why)—— 动机与价值的区别

  • 为什么需要 OOP?(解决复杂度与重用性)

    • 核心痛点: 传统的面向过程代码像面条一样纠缠,难以维护。
    • 价值: 通过封装、继承和多态,让代码逻辑清晰、易于重用。它解决了“如何构建业务核心模型”的问题。
    • 局限: 当多个不相关的业务模块都需要同一个功能(比如都要记录日志)时,OOP 只能在每个模块里都写一遍,导致代码冗余(代码散射)。
  • 为什么需要 AOP?(解决代码解耦与关注点分离)

    • 核心痛点: 核心业务逻辑中混杂了太多的非业务逻辑(如权限校验、日志打印),导致主逻辑不清晰。
    • 价值: 实现关注点分离(SoC)。让开发者专注于业务逻辑,而将通用的技术支撑功能统一管理。它解决了“如何优雅地处理跨模块的公共逻辑”的问题。

3. 怎么做(How)—— 实现与手段的区别

  • OOP 的手段:封装、继承、多态

    • 通过定义 Interface(接口)和 Class(类)。
    • 通过 extends(继承)来实现父子关系。
    • 在 NestJS 中,通过 @Injectable()constructor 注入依赖。
  • AOP 的手段:代理、拦截、织入

    • 核心组件:
      • 切点(Pointcut): 定义在“哪里”拦截(比如所有以 find 开头的方法)。
      • 通知(Advice): 定义“什么时候”干什么(方法执行前、后、还是异常时)。
      • 切面(Aspect): 切点 + 通知。
    • 在 NestJS 中的落地:
      • 你之前问过的 Guards(守卫)Interceptors(拦截器)Exception Filters(异常过滤器) 都是 AOP 的具体实现。
      • 底层通常使用 Proxy(代理模式),在不修改原代码的情况下,动态地将功能植入。

综合对比总结

维度面向对象 (OOP)面向切面 (AOP)
思维维度纵向(业务领域建模)横向(技术关注点提取)
核心单位类 (Class) / 对象 (Object)切面 (Aspect)
解决的问题把复杂系统拆解为独立的个体把散落在各处的通用功能聚合
代码关系继承、组合、嵌套拦截、注入、织入
在 NestJS 中定义 Service、Controller 处理业务定义 Guard 处理权限,Interceptor 记录日志

一句话总结: OOP 负责把房子盖好(客厅、卧室、厨房职能分明),而 AOP 负责在所有的房间里安装统一的电路和烟雾报警器(不管你是客厅还是卧室,安全和供电是横向贯穿的)。