2025-10-27
一言
江畔何人初见月,江月何年初照人? --- 《春江花月夜》 · 唐代 张若虚
Details
全文
春江潮水连海平,海上明月共潮生。滟滟随波千万里,何处春江无月明!
江流宛转绕芳甸,月照花林皆似霰。
空里流霜不觉飞,汀上白沙看不见。
江天一色无纤尘,皎皎空中孤月轮。
江畔何人初见月,江月何年初照人?
人生代代无穷已,江月年年只相似。
不知江月待何人,但见长江送流水。
白云一片去悠悠,青枫 浦上不胜愁。
谁家今夜扁舟子,何处相思明月楼?
可怜楼上月徘徊,应照离人妆镜台。
玉户帘中卷不去,捣衣砧上拂还来。
此时相望不相闻,愿逐月华流照君。
鸿雁长飞光不度,鱼龙潜跃水成文。
昨夜闲潭梦落花,可怜春半不还家。
江水流春去欲尽,江潭落月复西斜。
斜月沉沉藏海雾,碣石潇湘无限路。
不知乘月几人归,落月摇情满江树。
代码重构中的设计模式与工程思想学习笔记
一、背景概述
本次重构的目标不是为了改变业务逻辑,而是通过优化代码结构,让系统更具 可读性、可扩展性、可维护性。 在优化过程中,主要体现了多种经典的设计模式与工程原则,包括:
- Facade(门面模式)
- DTO(数据传输对象模式)
- Value Object(值对象模式)
- Adapter / Anti-Corruption Layer(适配层 / 防腐层思想)
- 接口分离原则(Interface Segregation)
- 组合优于继承
- 防卫式编程(Guard Clauses)
这些设计理念相互配合,使得代码结构清晰、 职责划分明确、可扩展性强。
二、主要模式与思想讲解
1. Facade(门面模式)
核心思想: 为复杂的子系统提供一个统一的调用接口,使上层代码不需要了解内部实现细节。
在本项目中的体现:
Service类承担了门面角色,对外只暴露简单的业务方法;- 内部封装了调用顺序、异常捕获、日志记录、数据校验等逻辑;
- 外部模块只需调用一个方法,即可完成整个业务流程。
优点:
- 调用方代码极度简化;
- 屏蔽内部复杂性;
- 便于单元测试与后期维护。
2. DTO(Data Transfer Object)模式
核心思想: 用于在系统间传递数据的简单对象,不包含业务逻辑,仅负责数据封装。
设计要点:
- 所有输入输出数据统一封装为 DTO;
- 使用泛型 DTO 结构,提高通用性;
- 利用 JSON 注解与序列化 工具实现自动映射。
优点:
- 解耦业务逻辑与数据结构;
- 易于扩展字段;
- 支持泛型化封装,提高代码复用率。
3. Value Object(值对象模式)
核心思想: 用来封装不可变的数据结构,只关心“值”而非“身份”。
对应实现:
private record Sec(String token, String cookie) {}
特点:
- 不可变(
record字段为final); - 自带构造器、访问器、
equals、hashCode; - 语义清晰,专注表达数据本身。
优点:
- 无副作用;
- 安全可复用;
- 代码更简洁,逻辑更纯粹。
4. Adapter / Anti-Corruption Layer(适配层 / 防腐层)
核心思想: 当外部系统或外部数据格式不便直接使用时,通过适配层将其转换为内部统一结构。
设计要点:
- 通过中间层 DTO(如
ODataResponse<T>)屏蔽外部格式; - 内部代码只关心统一的数据模型,不关心外部数据结构;
- 如果外部接口发生变化,仅需调整适配层即可。
优点:
- 避免外部依赖侵入内部代码;
- 减少变更影响面;
- 提升系统 稳定性。
5. 接口分离原则(Interface Segregation Principle, ISP)
核心思想: 一个接口应该只包含调用方真正关心的功能,不应该强迫实现类依赖无关方法。
实现方式:
public interface HasStatusMessage {
String getStatus();
String getMessage();
}
设计意图:
- 不使用继承公共父类;
- 仅约束最小必要能力(状态与消息获取);
- 让任意对象只需实现该接口即可被统一处理。
优点:
- 降低耦合;
- 方便扩展;
- 代码更具灵活性。
6. 组合优于继承(Composition Over Inheritance)
核心思想: 优先使用组合来实现代码复用,而不是通过继承。
改进前:
public class TableResult extends Result { ... }
public class MaskResponse extends Result { ... }
改进后:
public class TableResult implements HasStatusMessage { ... }
public class MaskResponse implements HasStatusMessage { ... }
优点:
- 继承层级变浅;
- 避免父类字段污染;
- 不同对象可灵活实现相同接口;
- 更易单测与维护。
7. 防卫式编程(Guard Clauses)
核心思想: 在进入主要逻辑前先验证前提条件,一旦不满足,立即中断执行。
示例:
private void ensureHttpOk(ResponseEntity<?> response) {
if (response.getStatusCode().isError()) {
throw new IllegalStateException("HTTP调用失败");
}
if (response.getBody() == null) {
throw new IllegalArgumentException("响应体为空");
}
}
优点:
- 错误发现早;
- 逻辑路径清晰;
- 避免深层嵌套的 if-else。
三、整体结构关系图
┌───────────────────────────────┐
│ Service(Facade) │
│ ├─ 调用封装与业务整合 │
│ ├─ 异常与日志统一处理 │
│ └─ 返回标准化 DTO │
└────────────┬──────────────────┘
│ uses
┌────────────▼──────────────────┐
│ Adapter / DTO 层 │
│ ODataResponse<T> │
│ 将外部格式转为内部结构 │
└────────────┬──────────────────┘
│
┌────────────▼──────────────────┐
│ 各种结果类实现接口能力 │
│ (HasStatusMessage) │
└───────────────────────────────┘
四、设计思想总结
| 思想/模式 | 核心目标 | 在代码中的体现 |
|---|---|---|
| Facade | 简化调用接口 | Service 封装完整流程 |
| DTO | 数据传输解耦 | ODataResponse<T>、Result 等 |
| Value Object | 不可变数据表达 | record Sec(...) |
| Adapter/防腐层 | 屏蔽外部差异 | 统一解析外部结构 |
| 接口分离 | 最小化依赖 | HasStatusMessage |
| 组合优于继承 | 降低耦合 | implements 替代 extends |
| 防卫式编程 | 提高健壮性 | ensureOk* 系列方法 |
五、关键收获
- 先抽象职责,再考虑复用 —— 每个类的存在都应有清晰的“唯一责任”;
- 接口表达能力,类表达身份 —— 使用接口描述行为约束比继承更灵活;
- 内部模型应与外部协议解耦 —— 防止外部变动破坏内部稳定;
- 局部封装优于全局暴露 —— 内部工具类型如
record Sec保持私有即可; - 简洁即力量 —— 少即是多,清晰的边界比复杂的层次更有价值。
六、结语
这次重构的核心思想是:
以职责边界为中心,用模式解决问题,而不是堆砌模式。
通过合理运用 Facade、DTO、Value Object、接口分离等模式,代码实现了更高的内聚度和更低的耦合度。 最终结果不仅让结构更优雅,也让后续功能扩展、调试与测试都更加轻松。