目录
一、引言:什么是软件架构风格
软件架构风格(Architectural Style)是描述某一特定应用领域中系统组织方式的惯用模式。它定义了一组构件类型、一组连接件类型、一组拓扑约束,以及一组语义约束。通俗来说,架构风格就是"设计软件的模板"——它规定了系统由哪些部件组成、部件之间如何连接、整体呈现什么形态。
软件架构风格是描述某一特定应用领域中系统组织方式的惯用模式。架构风格定义了:
1. 构件类型:系统中存在哪些计算元素(如过滤器、层、对象)
2. 连接件类型:构件之间如何交互(如管道、调用、事件)
3. 拓扑约束:构件和连接件如何组合排列
4. 语义约束:行为层面的限制条件
理解架构风格的意义在于:它为架构师提供了一套设计词汇表和设计模式库,使得架构设计不再是"从零开始",而是在成熟模式的基础上做权衡和定制。在软考(系统架构设计师)中,架构风格是每年必考的核心知识点。
二、架构风格分类总览
Garlan 和 Shaw 将经典软件架构风格分为五大类。这是软考中最核心的分类框架,必须牢记:
除了这五大经典分类外,还有 C/S、B/S、MVC、SOA、REST、微服务等现代架构风格,它们是在经典风格基础上的演进和组合。下面逐一深入讲解。
三、数据流风格
数据流风格的核心特征是:数据在构件之间流动,每个构件对输入数据进行变换处理,产生输出数据。构件之间通过数据流连接,不存在显式的控制调用关系。
3.1 批处理序列(Batch Sequential)
批处理是最古老的数据流风格。每个处理步骤是一个独立的程序,前一步的完整输出作为后一步的输入,步骤之间是顺序执行的,必须等前一步全部完成才能开始下一步。
特征要点
- 构件:独立的应用程序(批处理程序)
- 连接件:文件(数据以文件形式在步骤间传递)
- 执行模式:严格顺序,前一步完成后才启动下一步
- 典型应用:编译器的词法分析→语法分析→语义分析→代码生成;银行日终结算;数据仓库 ETL 流程
优点
- 每个步骤独立,可以单独设计、测试和维护
- 步骤间通过文件解耦,延迟低耦合
- 适合处理大量数据,吞吐量高
缺点
- 无法增量处理,必须等全部数据就绪
- 实时性差,延迟高
- 中间文件I/O开销大
3.2 管道-过滤器风格(Pipe-Filter)
管道-过滤器风格是数据流风格中最重要的子类型。与批处理不同,过滤器可以增量式地处理数据——不需要等全部数据到齐,来一个处理一个,像流水线一样持续工作。
· 过滤器(Filter):独立的数据处理构件,读取输入流,进行变换,产生输出流。过滤器之间不共享状态
· 管道(Pipe):数据传输通道,连接过滤器的输出到下一个过滤器的输入,起缓冲作用
· 关键特性:过滤器可以增量处理(来一条数据处理一条),多个过滤器可以并行执行
优点
- 支持增量处理,实时性好
- 过滤器独立,高内聚低耦合,复用性强
- 支持并行执行,吞吐量高
- 易于理解和维护,流水线结构清晰
- 新增/替换过滤器方便,扩展性好
缺点
- 不适合交互式系统
- 过滤器间数据格式必须兼容,难以处理异构数据
- 每个过滤器都需要解析和格式化数据,性能开销
- 错误处理困难,某个过滤器出错影响整条管道
· 批处理:整批数据传递,顺序执行,不能并行
· 管道-过滤器:增量数据传递,可并行执行
· 二者同属数据流风格,区别在于"数据传递粒度"和"执行并行性"
四、调用/返回风格
调用/返回风格是最常见的架构风格族。其核心特征是:构件之间通过显式的调用-返回机制进行交互,存在控制流传递关系。
4.1 主程序-子程序风格
最古老的架构风格之一。系统被分解为一个主程序和若干子程序,主程序调用子程序,子程序再调用更下层的子程序,形成树状调用结构。
特征要点
- 构件:主程序、子程序(过程/函数)
- 连接件:调用-返回机制
- 结构:树状层次结构,单入口(主程序)
- 典型应用:早期Fortran/Cobol程序,结构化程序设计
优点
- 结构清晰,容易理解
- 控制流明确,调试方便
- 对小型系统效率高
缺点
- 对大规模系统难以管理
- 子程序间通过共享数据耦合,修改风险大
- 不支持并发
4.2 面向对象风格
面向对象风格将系统分解为一组协作的对象,每个对象封装了数据和操作数据的方法。对象之间通过方法调用进行交互。
· 构件:对象(封装了数据和方法的实例)
· 连接件:方法调用(同步的函数调用)
· 关键特性:封装、继承、多态
· 与主程序-子程序的区别:对象封装了状态,调用者不需要知道被调用者的内部实现
优点
- 封装性强,内聚高耦合低
- 通过继承实现代码复用
- 多态性支持灵活扩展
- 与现实世界模型映射,易于理解
缺点
- 对象间通过引用调用,存在耦合
- 方法调用是同步的,影响性能
- 对象标识管理增加复杂度
4.3 层次结构风格
层次结构是最广泛使用的架构风格之一。系统被组织成若干层,每层为上层提供服务,同时调用下层的服务。层间通信通过定义良好的接口进行,不允许跨层调用。
· 构件:各层(Layer),每层封装特定功能
· 连接件:层间接口调用(协议)
· 关键约束:第 N 层只能调用第 N-1 层的服务,不允许跨层调用
· 典型应用:OSI 七层网络模型、操作系统内核层、企业应用三层架构
优点
- 支持基于可增加抽象层的设计,允许扩展功能
- 不同层之间相互透明,独立性高
- 支持复用,每层可以独立替换实现
- 可测试性好,每层可独立测试
- 标准化程度高,层间接口清晰
缺点
- 并非所有系统都适合分层
- 层次过多导致性能下降(逐层调用开销)
- 层间接口修改影响面大
- 跨层需求难以实现(严格分层过于死板)
· 严格分层:每层只能调用直接相邻的下层(如OSI模型)
· 非严格分层:允许跳过中间层调用更下层(如TCP/IP模型,应用层直接调用网络层)
· 考试中常问"某个架构属于哪种分层方式"
五、独立构件风格
独立构件风格的核心特征是:构件之间不存在显式的调用关系,而是通过事件的发布和订阅进行隐式交互。构件是松散耦合的,彼此独立运行。
5.1 事件驱动/隐式调用风格
事件驱动风格中,构件通过发布事件和订阅事件来交互。事件的发布者不需要知道谁会处理这个事件,处理者也不需要知道事件从哪来——这种解耦方式被称为"隐式调用"。
· 构件:事件发布者、事件订阅者、事件处理器
· 连接件:事件总线(Event Bus)/ 消息代理
· 关键特性:构件之间没有显式调用,通过事件隐式触发。发布者不知道谁订阅,订阅者不知道谁发布
· 典型应用:GUI 事件系统(点击、键盘)、Node.js 事件循环、消息队列(Kafka/RabbitMQ)、Vue/React 的响应式系统
优点
- 松耦合,构件之间相互独立
- 可扩展性强,新增订阅者不影响发布者
- 支持异步处理,响应性好
- 适合分布式系统和实时系统
缺点
- 控制流难以追踪(事件触发链路不直观)
- 事件顺序不可控(除非使用有序队列)
- 调试和测试困难
- 可能导致事件风暴(事件级联触发)
5.2 进程通信风格
进程通信风格中,构件是独立进程,通过网络协议或消息传递进行通信。这是分布式系统的基础风格。
特征要点
- 构件:独立进程
- 连接件:消息传递(RMI、RPC、消息队列)
- 关键特性:进程间通过定义良好的协议通信,支持分布式部署
- 典型应用:微服务间通信、分布式系统、CORBA/DCOM
六、虚拟机风格
虚拟机风格的核心特征是:引入一个虚拟机层,将高层抽象解释为底层可执行操作。这种风格适合需要"运行时解释"或"规则推理"的场景。
6.1 解释器风格
解释器风格包含一个解释器引擎,它读取并执行某种语言的源代码或字节码,逐条解释执行。
解释器风格核心要素
- 构件:解释器引擎、被解释的程序(源代码)、解释器状态
- 连接件:解释器内部的调用机制
- 关键特性:运行时解释执行,不需要编译
- 典型应用:编程语言解释器(JVM、CPython)、DSL 引擎、规则引擎、SQL 解释器
优点
- 灵活性高,可在运行时修改逻辑
- 适合DSL和动态语言
- 跨平台(只要解释器存在)
缺点
- 执行效率低(逐条解释)
- 解释器实现复杂
- 运行时错误难以提前发现
6.2 基于规则的系统
基于规则的系统是解释器风格的特例,专门用于知识推理。它包含一组规则(If-Then),一个工作内存(事实库),和一个推理引擎(前向链/反向链推理)。
特征要点
- 构件:规则库、工作内存(事实库)、推理引擎
- 连接件:规则匹配机制
- 典型应用:专家系统、智能诊断、风控规则引擎、推荐系统
七、仓库风格
仓库风格的核心特征是:系统中存在一个中央数据仓库,所有构件共享访问这个仓库。构件之间不直接通信,而是通过读写中央仓库间接交互。
7.1 数据库系统风格
最简单的仓库风格。中央仓库是数据库,构件通过SQL等方式读写数据。构件之间通过共享数据间接耦合。
7.2 黑板系统风格
黑板系统是仓库风格中最重要、考试频率最高的子类型。它由三个主要部分组成:知识源、黑板、控制器。
1. 知识源(Knowledge Source, KS):独立的专家模块,各自负责特定领域的知识处理。监控黑板状态,当条件满足时触发执行
2. 黑板(Blackboard):共享数据结构,存储问题求解过程中的中间状态和结果。按层次组织数据
3. 控制器(Controller):调度中枢,监控黑板变化,根据策略选择下一个执行的知识源
工作流程:知识源监控黑板 → 条件满足时向控制器注册 → 控制器选择最合适的知识源执行 → 知识源读写黑板 → 循环直到问题解决
优点
- 适合不确定性问题求解
- 知识源独立,可复用可扩展
- 支持多种知识表示方法
- 适合AI和专家系统
缺点
- 控制策略复杂
- 调试困难(执行顺序不确定)
- 性能开销大(频繁扫描黑板)
黑板系统适用于解空间很大、需要多个不同领域知识协作、求解过程不确定的复杂问题。典型应用:语音识别、图像理解、自然语言处理、专家系统。
记忆口诀:黑板 = 知识源 + 黑板 + 控制器 = 三件套
7.3 超文本系统风格
超文本系统以超链接为核心组织信息,数据节点通过链接相互关联,形成网状结构。
特征要点
- 构件:超文本节点(页面)
- 连接件:超链接
- 典型应用:Web 应用、Wiki 系统、文档管理系统
八、C/S 与 B/S 架构
8.1 C/S 架构(客户端/服务器)
C/S 架构将系统分为客户端和服务器两部分。客户端负责用户界面和部分业务逻辑,服务器负责数据管理和核心业务逻辑。
C/S 架构的演进经历了多个阶段:
| 阶段 | 结构 | 特点 |
|---|---|---|
| 两层 C/S | 客户端 + 数据库服务器 | 客户端承担UI+业务逻辑,服务器只管数据。胖客户端 |
| 三层 C/S | 客户端 + 应用服务器 + 数据库 | 业务逻辑移到应用服务器,客户端变瘦。中间件出现 |
| N 层 C/S | 客户端 + 多级服务器 + 数据库 | 引入Web服务器、缓存层等,层次更多更灵活 |
C/S 优点
- 客户端响应速度快(本地有缓存和逻辑)
- 服务器负载较轻
- 可充分利用客户端硬件能力
- 安全可控(自定义协议)
C/S 缺点
- 需要安装客户端,升级维护成本高
- 跨平台困难(不同OS需开发不同客户端)
- 开发成本高(客户端+服务器两套代码)
- 用户基数有限(需安装才能使用)
8.2 B/S 架构(浏览器/服务器)
B/S 架构是 C/S 的特例,客户端统一使用浏览器,无需安装专用客户端程序。
B/S 优点
- 零安装,用户只需浏览器
- 跨平台,一次开发到处运行
- 升级维护在服务端完成,客户端自动获取最新版本
- 用户基数无限制,易于推广
B/S 缺点
- 服务器压力大(所有逻辑在服务端)
- 响应速度受网络影响
- 交互体验不如原生客户端
- 安全性挑战(HTTP明文传输需HTTPS)
九、MVC 及其衍生架构
9.1 MVC(Model-View-Controller)
MVC 是最经典的前端/应用架构模式,将系统分为三个核心部分:模型、视图、控制器。
· Model(模型):管理业务数据和状态,包含业务逻辑。独立于View和Controller
· View(视图):负责UI渲染。监听Model变化,自动刷新显示
· Controller(控制器):接收用户输入,调度Model和View。是MVC的协调中枢
核心关系:Controller → Model(更新数据)、Controller → View(选择视图)、Model → View(通知更新)
9.2 MVP(Model-View-Presenter)
MVP 是 MVC 的演进版本。关键变化是:View 和 Model 不再直接通信,所有交互通过 Presenter 中转。
9.3 MVVM(Model-View-ViewModel)
MVVM 在 MVP 基础上引入了双向数据绑定,ViewModel 和 View 之间自动同步状态,无需手动更新。
MVVM 核心特点
- ViewModel:包含 View 需要的数据和命令,通过数据绑定与 View 关联
- 双向绑定:View 变化自动反映到 ViewModel,ViewModel 变化自动更新 View
- View 被动:只负责渲染,不含任何业务逻辑
- 典型框架:Vue.js、Angular、WPF/SL、Knockout.js
| 维度 | MVC | MVP | MVVM |
|---|---|---|---|
| View 与 Model 通信 | 允许(Model通知View) | 禁止(通过Presenter) | 禁止(通过ViewModel) |
| 控制器/中介角色 | Controller | Presenter | ViewModel |
| View 更新方式 | 手动 | 手动(Presenter调用View接口) | 自动(数据绑定) |
| 可测试性 | 一般 | 好 | 最好 |
| 典型应用 | Spring MVC、Django | Android、WinForms | Vue.js、Angular、WPF |
十、RPC 架构
RPC(Remote Procedure Call,远程过程调用)允许程序调用另一个地址空间(通常在另一台机器上)的过程/函数,就像调用本地过程一样。
1. 客户端调用本地 Client Stub(就像调用本地函数)
2. Client Stub 将参数序列化为网络消息
3. 消息通过网络发送到服务端
4. Server Stub 接收消息,反序列化参数
5. Server Stub 调用真正的服务方法
6. 服务方法执行完毕,返回结果给 Server Stub
7. Server Stub 将结果序列化并通过网络返回
8. Client Stub 接收并反序列化结果,返回给客户端
十一、SOA 架构
SOA(Service-Oriented Architecture,面向服务架构)将应用程序分解为一组松耦合的服务,服务之间通过标准协议(如 SOAP/WSDL)通信。
· 服务:独立的、可复用的业务功能单元
· ESB(企业服务总线):服务间的通信中枢,负责路由、协议转换、消息转换、编排
· 松耦合:服务之间通过标准接口通信,互不知道内部实现
· 典型技术:SOAP + WSDL + UDDI(Web Service 技术栈)
· 与微服务的区别:SOA 偏重企业级集成,服务粒度粗,依赖 ESB;微服务偏重互联网应用,服务粒度细,去中心化
十二、REST 架构风格
REST(Representational State Transfer,表述性状态转移)是 Roy Fielding 在 2000 年博士论文中提出的网络应用架构风格。它不是协议,而是一组架构约束。
1. 客户端-服务器:分离 UI 和数据存储,提升可移植性和可扩展性
2. 无状态:每个请求包含所有必要信息,服务器不保存客户端状态
3. 可缓存:响应必须明确标识是否可缓存,提升网络效率
4. 统一接口:资源标识(URI)、资源操作(HTTP方法)、自描述消息、HATEOAS
5. 分层系统:客户端不需要知道直接连接的是服务器还是中间件
6. 按需代码(可选):服务器可向客户端发送可执行代码(如JS)
十三、微服务架构
微服务架构是将单体应用拆分为一组小型、自治的服务,每个服务独立部署、独立扩展、独立技术栈。
· 服务自治:每个服务独立开发、部署、运维、扩展
· 独立数据库:每个服务拥有自己的数据库,不共享
· 去中心化:无 ESB,服务间点对点通信(REST/gRPC/MQ)
· 技术多样性:不同服务可使用不同语言和框架
· 基础设施:API Gateway、服务注册发现、配置中心、链路追踪、容器化(Docker/K8s)
| 维度 | SOA | 微服务 |
|---|---|---|
| 通信方式 | ESB 企业服务总线(中心化) | REST/gRPC/MQ(去中心化) |
| 服务粒度 | 粗粒度(业务级) | 细粒度(功能级) |
| 数据共享 | 可共享数据库 | 每服务独立数据库 |
| 部署方式 | 整体部署 | 独立部署(容器化) |
| 技术栈 | 通常统一 | 可多样化 |
十四、富互联网应用(RIA)
RIA(Rich Internet Application)结合了桌面应用的丰富交互体验和 Web 应用的易部署特性。
RIA 核心特征
- 富交互:拖拽、动画、局部刷新,接近桌面应用体验
- 客户端计算:大量逻辑在浏览器端执行,减轻服务器压力
- 异步通信:通过 AJAX/Axios 与服务器异步交互,无需刷新页面
- 典型技术:AJAX、SPA(单页应用)、Vue/React/Angular、Flex/Sliverlight(已淘汰)
十五、架构风格对比与选型
| 架构风格 | 构件 | 连接件 | 关键特征 | 适用场景 |
|---|---|---|---|---|
| 批处理 | 独立程序 | 文件 | 顺序执行,整批传递 | 编译器、ETL、日终结算 |
| 管道-过滤器 | 过滤器 | 管道 | 增量处理,可并行 | Unix Shell、数据流处理 |
| 面向对象 | 对象 | 方法调用 | 封装、继承、多态 | 大多数现代软件 |
| 分层 | 层 | 层间接口 | 逐层调用,禁止跨层 | OSI模型、企业三层架构 |
| 事件驱动 | 构件/处理器 | 事件总线 | 隐式调用,松耦合 | GUI、消息系统、IoT |
| 解释器 | 解释引擎 | 内部调用 | 运行时解释执行 | JVM、Python、SQL引擎 |
| 黑板 | 知识源 | 黑板+控制器 | 共享状态,协作求解 | 语音识别、专家系统 |
| C/S | 客户端+服务器 | 网络协议 | 胖客户端,需安装 | 企业内部系统、游戏 |
| B/S | 浏览器+服务器 | HTTP | 零安装,跨平台 | Web应用、SaaS |
| MVC | M/V/C | 方法调用+观察 | 关注点分离 | Web框架、桌面应用 |
| REST | 资源 | HTTP方法 | 无状态,统一接口 | API设计、微服务 |
| 微服务 | 独立服务 | REST/gRPC/MQ | 独立部署,独立DB | 大型互联网应用 |
· 需要数据流式处理 → 管道-过滤器
· 需要层次清晰、接口标准化 → 分层
· 需要松耦合、异步交互 → 事件驱动
· 需要运行时灵活性 → 解释器
· 需要多领域知识协作 → 黑板系统
· 需要跨平台、零安装 → B/S
· 需要高性能、强交互 → C/S
· 需要大规模、独立扩展 → 微服务
十六、总结
软件架构风格是系统架构设计师考试的核心高频考点,也是实际架构设计的基础工具箱。掌握架构风格的关键在于理解每种风格的构件类型、连接件类型、拓扑结构和适用场景。
1. 五大分类必须精确记忆:数据流、调用/返回、独立构件、虚拟机、仓库
2. 每种子风格的归属:管道-过滤器属于数据流、分层属于调用/返回、事件驱动属于独立构件、解释器属于虚拟机、黑板属于仓库
3. 黑板系统三件套:知识源 + 黑板 + 控制器
4. MVC 三者关系:Controller→Model、Controller→View、Model→View(通知)
5. REST 六大约束:客户端-服务器、无状态、可缓存、统一接口、分层系统、按需代码
6. SOA vs 微服务:ESB 中心化 vs 去中心化、粗粒度 vs 细粒度
7. RPC 流程:Client Stub → 序列化 → 网络 → Server Stub → 反序列化 → 执行 → 返回
8. 优缺点对比:每种风格至少记住 3 个优点 + 2 个缺点
架构风格不是非此即彼的选择,实际系统往往是多种风格的组合。例如,一个微服务系统内部可能使用分层架构,服务间使用 REST 通信,前端使用 MVC/MVVM,日志系统使用管道-过滤器风格。架构师的价值在于根据业务需求、团队能力、技术约束做出合理的权衡与组合。