架构模式与设计模式

厘清架构模式(Architectural Patterns)与设计模式(Design Patterns)的本质区别,深入掌握分层架构、管道-过滤器、微内核、事件驱动等经典架构模式的适用场景与实现策略。

架构模式与设计模式

许多开发者将架构模式与设计模式混为一谈,实际上二者关注的抽象层次截然不同:设计模式解决类与对象级别的协作问题,架构模式解决系统级别的组织与交互问题。本文系统梳理二者的本质差异,并深入讲解六大经典架构模式。


1. 本质区别

1.1 关注点

维度设计模式 (GoF 23)架构模式
抽象层次类/对象子系统/模块/服务
影响范围单个模块内部整个系统的拓扑结构
代码量数十行到数百行数千行到数万行
演变更本较低(重构类关系)极高(改动系统骨架)
典型数量约 23 个经典模式约 10+ 大架构模式 + N 种变体
示例工厂、单例、观察者分层、微服务、事件溯源

1.2 关系图

单一职责原则(SOLID)
    ↓ 指导
设计模式(GoF 23)←→ 架构模式(10+)
    ↓ 解决问题层次不同

设计模式 ≈ 房屋内部的家具摆放方式
架构模式 ≈ 房屋本身的结构布局(几室几厅、承重墙位置)

2. 六大经典架构模式

2.1 分层架构(Layered Architecture)

最经典、最广泛使用的架构模式,将软件按职责垂直划分为多个层次。

┌──────────────────────────┐
│     表示层(Presentation)  │  ← UI、API、控制器
├──────────────────────────┤
│     业务逻辑层(Business)  │  ← 领域模型、服务编排
├──────────────────────────┤
│     数据访问层(Data)      │  ← DAO、Repository
├──────────────────────────┤
│     数据库层(Database)    │  ← 关系型/NoSQL
└──────────────────────────┘

依赖规则:上层可调用下层,下层不可反向依赖
跨层通信:建议通过 DTO 进行数据传输

变体:N-Tier(物理分层)

Web 服务器(Tier 1)→ 应用服务器(Tier 2)→ 数据库服务器(Tier 3)
每台服务器可独立扩展,使用网络协议通信而非内存调用

适用场景:传统企业应用(ERP、CRM)、中小型 Web 应用、初学者入门项目。

常见反模式

  • ** spaghetti 式分层**:上层直接绕过中间层调用底层
  • 贫血领域模型:业务逻辑全在 Service 层,Entity 只有 getter/setter

2.2 管道-过滤器(Pipes and Filters)

将数据处理过程分解为一系列独立的过滤组件,通过管道连接。

数据输入 → [过滤器 A] ──管道──→ [过滤器 B] ──管道──→ [过滤器 C] → 数据输出
              │                    │                    │
           读取文件             数据转换              写入输出

Unix Shell 示例:
cat log.txt | grep "ERROR" | awk '{print $5}' | sort | uniq -c
  读取      过滤错误行         提取第5列        排序    统计频率

适用场景:编译器(词法分析→语法分析→语义分析→代码生成)、音视频处理管道、ETL 数据处理、日志分析系统。

优点

  • 过滤器可独立开发、测试和复用
  • 管道支持并行化执行(流式处理)
  • 系统扩展简单(新增过滤器即可)

缺点

  • 数据格式需统一(兼容性成本)
  • 不适合交互性强、需要状态共享的场景

2.3 微内核/插件架构(Microkernel)

核心系统提供最小化运行环境,功能通过插件动态扩展。

┌─────────────────────────────────┐
│         插件管理器(Plugin Manager)│
│  ┌──────────┐  ┌──────────┐     │
│  │ 插件 A    │  │ 插件 B    │ ... │
│  └──────────┘  └──────────┘     │
├─────────────────────────────────┤
│  核心服务(Core)                 │
│  - 生命周期管理                   │
│  - 事件总线                       │
│  - 模块加载器                     │
│  - 配置管理                       │
└─────────────────────────────────┘

示例:
- IDE(VS Code、IntelliJ)
- 浏览器(Chrome 扩展)
- 游戏引擎(UE4/Unity 插件系统)
- Jenkins(流水线插件)

关键设计决策

维度选择
插件间通信通过核心事件总线(松耦合)或直接 API 调用(高性能)
隔离机制OSGi classloader 隔离 / Docker 容器隔离 / 进程隔离
部署方式动态热加载 / 重启生效

2.4 事件驱动架构(Event-Driven Architecture, EDA)

组件间通过异步事件而非直接调用来通信,实现高度解耦。

                    ┌────────────┐
    订单服务 ──事件──→│ 事件总线    │
                    │ (Kafka/    │
  库存服务 ←──订阅───│  RabbitMQ) │
                    │            │
  通知服务 ←──订阅───│            │
                    └────────────┘

优势:
- 发布者和订阅者互不知晓
- 可独立扩展消费者
- 天然支持事件溯源(Event Sourcing)

三种事件模式

模式说明示例
事件通知只通知发生了某事,不携带详情“订单已创建”
事件携带状态包含事件相关的完整数据“订单已创建 + 订单详情”
事件溯源以事件序列作为系统状态的唯一来源所有状态变化 = 事件日志

缺点与应对

  • 最终一致性:需设计补偿事务(Saga 模式)
  • 事件乱序:Kafka 分区保证局部有序,全局有序需额外设计
  • 调试困难:请求链路跨越多个服务 → 分布式追踪必配

2.5 微服务架构(Microservices)

将单一应用拆分为一组小型服务,每个服务独立部署、独立扩展。

API Gateway
    │
    ├──→ 用户服务(Users)    —→ 用户数据库
    ├──→ 订单服务(Orders)   —→ 订单数据库
    ├──→ 库存服务(Inventory)—→ 库存数据库
    ├──→ 支付服务(Payment)  —→ 支付数据库
    └──→ 通知服务(Notify)   —→ 消息队列

拆分策略

策略依据优点风险
按业务领域(DDD)限界上下文天然高内聚需深入领域理解
按功能(CRUD)实体类型直观简单易过小导致管理成本
按团队(康威定律)组织结构团队自治技术栈可能碎片化

何时不选微服务

  • 团队 < 20 人
  • 请求 QPS < 1000
  • 没有自动化部署/监控基础设施
  • 业务领域边界不清晰

2.6 空间架构/基于网格的架构(Space-Based Architecture)

消除中心数据库瓶颈,将数据和处理单元分布到网格节点。

┌─────────────────────────────────────────┐
│           负载均衡器(Load Balancer)      │
└─────────────────────────────────────────┘
     │            │            │
┌────────┐  ┌────────┐  ┌────────┐
│ 处理单元│  │ 处理单元│  │ 处理单元│
│ ┌────┐ │  │ ┌────┐ │  │ ┌────┐ │
│ │内存│ │  │ │内存│ │  │ │内存│ │  ← 数据缓存在内存
│ │Cache│ │  │ │Cache│ │  │ │Cache│ │
│ └────┘ │  │ └────┘ │  │ └────┘ │
└────────┘  └────────┘  └────────┘
     │            │            │
└─────────────────────────────────────────┘
│         数据总线/消息队列(Data Grid)      │
└─────────────────────────────────────────┘

适用场景:高并发读写系统(证券交易、在线游戏、实时竞价)。

代表产品:Hazelcast、Apache Ignite、GigaSpaces。


3. 架构模式选择决策树

是否需要处理大量并发用户?
  ├── 是 → 数据量极大?
  │         ├── 是 → 空间架构 / 微服务 + CQRS
  │         └── 否 → 微服务 / 事件驱动
  └── 否 → 数据流处理为主?
            ├── 是 → 管道-过滤器
            └── 否 → 需要高度可扩展性?
                      ├── 是 → 微内核 / 插件架构
                      └── 否 → 分层架构(默认选择)

4. 架构模式组合拳

实际系统很少只用一种架构模式,通常是多种模式组合

系统类型模式组合
电商平台分层(单体阶段)→ 微服务 + 事件驱动(演进阶段)
银行核心系统分层 + 微内核(插件化的业务规则)
实时交易系统空间架构 + 事件驱动
数据中台管道-过滤器(ETL)+ 事件驱动(数据变更流)
SaaS 平台多租户分层 + 微服务 + 微内核(可插拔模块)

5. 总结

架构模式:系统骨架(how to organize the system)
设计模式:模块细节(how to organize classes/objects within a module)

关系:架构模式 → 划定子系统边界 → 子系统内用设计模式实现细节

两者互补,缺一不可。只懂设计模式而忽视架构,会导致"精致的烂泥潭";
只谈架构而忽视设计模式,会导致"空中楼阁无法落地"。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页