软件架构风格:给准架构师的“选型地图”
这一章想做一件事:帮你把常见架构模式,装进一个清晰的“脑内索引”。
我选了 5 大类、十几种软件架构风格,它们几乎覆盖了你日常工作能碰到的大部分系统形态:
- 数据流风格
- 调用返回风格
- 独立构建风格
- 虚拟机风格
- 仓库风格
下面用技术博客的方式,帮你快速建立直觉:什么场景,优先往哪种风格上想。
一、数据流风格:一切皆“流”的世界
适用核心场景:有一条“主数据流”,经过多步加工。
典型子风格有两种:
-
批处理(Batch):
- 把一段时间的数据先“攒起来”,再统一处理;
- 特点:吞吐大、实时性弱、适合夜间任务、报表、T+1 结算等。
- 例子:
- 每天夜里跑的账单结算 / 对账任务;
- 按小时 / 按天跑的数据仓库 ETL。
-
管道-过滤器(Pipes & Filters):
- 数据像水流一样,通过一系列“过滤器”(Filter)依次处理;
- 每个过滤器专注做一件事,可以并行、可以复用;
- 例子:
- Linux 命令行
cat | grep | awk | sort; - 日志收集 → 清洗 → 解析 → 聚合 → 入库的实时链路。
- Linux 命令行
遇到这两类需求,可以优先考虑数据流风格:
- 原始数据 → 多步清洗 / 解析 / 聚合;
- 大量数据,但对毫秒级延迟没那么敏感;
- 可以接受“按窗口(时间/条数)”做处理。
二、调用返回风格:我们最熟悉的“按层调用”
适用核心场景:有一个“主流程”,通过函数 / 方法 / 层次逐步完成工作。
三种典型形态:
-
主程序-子程序(Main-Subroutine):
- 面向过程:主程序调用一堆子过程,子过程完成后返回;
- C 程序、简单脚本、工具类程序中非常常见。
-
面向对象(OO):
- 把状态和行为封装进对象里;
- 通过对象之间的调用协作完成业务;
- Java、C#、多数后端业务代码的常规写法。
-
分层结构(Layered Architecture):
- 典型如:控制层(Controller)→ 业务层(Service)→ 领域层 / 仓储层(Domain/Repository);
- 或者表示层 / 应用层 / 领域层 / 基础设施层。
你日常写的大多数 Web / 后台服务,本质上都是这三种的组合。
当你遇到这样的需求:
- 有清晰的“输入-处理-输出”主流程;
- 可以自然地分出展示层 / 业务层 / 数据访问层;
- 每一层都有明确职责边界;
就可以想到:本质是调用返回风格,只是用 OO + 分层结构把它组织得更清晰。
三、独立构建风格:服务之间如何“互相打招呼”
适用核心问题:多个独立的模块 / 服务,要怎么通信更合适。
有两大主流子风格:
-
进程间通信(IPC)风格:
- 有明显的“调用者 / 被调用者”;
- 通过 HTTP/REST、gRPC、RPC 框架等实现;
- 适合:
- 同步请求响应;
- 对调用链路有明确的事务 / 一致性诉求。
-
事件驱动 / 消息队列风格:
- 生产者只负责发送事件 / 消息,不关心谁来处理;
- 消费者订阅感兴趣的事件,自主处理;
- 异步、解耦、天然适合削峰填谷;
- 适合:
- 订单创建后触发积分、通知、风控等异步流程;
- Webhook / 回调场景;
- 业务对“最终一致性”可以接受。
如果你发现:
- 模块越来越多,直接 HTTP 互调让耦合度飞涨;
- 大量业务其实不需要同步强一致;
可以先问自己两个问题:
- 哪些必须走 同步调用(IPC)?
- 哪些可以改为 事件驱动 / 消息通知?
这个判断,往往就是你从“写服务”走向“做架构”的起点。
四、虚拟机风格:让“程序跑在程序里”
别被名字误导,这里的“虚拟机”,不只是 KVM/VMware 那种物理虚机,更重要的是像 JVM 这种“程序的运行环境”。
两类典型子风格:
-
解释器风格:
- 比如 JVM、Python 解释器、SQL 引擎;
- 它们读你的“程序”(字节码、脚本、SQL),在一个虚拟环境中执行;
- 好处:
- 屏蔽底层平台差异;
- 提供统一的运行时能力(GC、安全沙箱、JIT 优化等)。
-
规则引擎 / 决策系统风格:
- 比如 Drools、各类业务规则平台;
- 业务人员通过图形界面 / 规则 DSL 定义逻辑,规则引擎负责解释执行;
- 常见于:
- 营销优惠策略(满减、阶梯价、黑名单等);
- 风控规则、审批流程策略。
当你遇到这些信号时,可以考虑虚拟机风格:
- 业务规则经常变,不想每次都改代码、发版;
- 希望把“规则配置权”交给业务,技术负责提供稳定执行环境;
- 需要在不同平台(多语言、多操作系统)统一执行一套逻辑。
五、仓库风格:所有人共享的那块“大黑板”
核心问题:数据被多人 / 多模块共享时,怎么组织和管理?
有三种典型子风格:
-
数据库风格(Repository as DB):
- 最常见:集中式数据库、数据仓库;
- 所有模块围绕一个(或一组)共享数据库组织读写;
- 好处:
- 数据一致性强;
- 易于集中管理和分析;
- 风险:
- 容易演化成“超巨大共享表+存储过程地狱”;
- 耦合度非常高,改一个地方牵一大片。
-
超文本系统(Hypertext):
- 更偏「文档、页面、链接」风格;
- 早期的 Wiki、静态内容分发、CMS 系统中较多。
-
黑板风格(Blackboard):
- 少见但很有意思;
- 想象一块共同的“黑板”:
- 各种“专家模块”轮流在黑板上写入 / 读取信息;
- 通过黑板上的状态推动问题逐步被解决;
- 常用于:
- 语音识别、复杂模式识别、组合推理系统。
对于普通业务系统,你更多会落在:
- 关系型 / NoSQL 数据库 + 缓存;
- 再通过领域划分 / 读写分离 / 事件溯源,控制“共享仓库”的复杂度。
黑板风格更多是“知道有这个武器”,未来碰到复杂 AI / 智能推理类场景时可以想到它。
六、把风格用在实战和面试上:三条建议
1. 遇到系统设计题,先在脑子里“归类到某个风格”
比如:
- 问“Web 应用服务器如何处理 HTTP 报文和 SOAP 报文?”
- 你可以答:核心是 管道-过滤器风格 + 分层结构风格。
- 问“操作系统 GUI 事件是怎么处理的?”
- 可以谈:事件驱动(独立构建风格里的消息 / 事件子风格)。
- 问“Java 一次编写,到处运行靠的是什么?”
- 很自然地说:虚拟机风格里的解释器(JVM)。
2. 不要强行说“这个系统只有一种风格”
绝大多数真实系统都是多风格组合:
- Web 应用 = 调用返回(分层) + 独立构建(REST 调用 / MQ 事件) + 仓库(数据库风格);
- 大数据平台 = 数据流(批处理 + 流式管道) + 仓库(数据湖 / 数仓) + 虚拟机(SQL 引擎)。
你可以在回答中自然地说:
- “主干用的是 X 风格,Y 部分比较适合 Z 风格,所以我们做了拆分。”
这会让你的答案看起来既专业又不死板。
3. 回去看自己的系统,给它做一次“风格体检”
可以自问:
- 当前系统主要是哪些风格?有没有“用错风格”的地方?
- 哪些同步调用其实可以改成事件驱动,降低耦合?
- 哪些批任务其实可以“流式化”,减少延迟?
- 哪些规则应该从代码里抽离到“规则引擎式”的虚拟机?
当你能用“风格语言”来描述和优化自己的系统,你就不只是“堆技术栈”,而是在有意识地做架构。