设计原则速查
SOLID 原则
详见 SOLID 原则专题。
| 原则 | 缩写 | 一句话 | 违反症状 |
|---|---|---|---|
| 单一职责 | SRP | 一个类只做一件事 | 一个类因多个无关原因而修改 |
| 开闭原则 | OCP | 对扩展开放,对修改关闭 | 新增功能迫使稳定模块反复修改 |
| 里氏替换 | LSP | 子类能替换父类 | 子类重写后行为不一致 |
| 接口隔离 | ISP | 接口要小而专 | 实现类被迫实现不需要的方法 |
| 依赖倒置 | DIP | 依赖抽象而非具体 | 高层模块直接依赖低层实现 |
其他原则
详见 其他设计原则专题。
| 原则 | 说明 |
|---|---|
| DRY | Don't Repeat Yourself,消除重复 |
| KISS | Keep It Simple, Stupid,保持简单 |
| YAGNI | You Aren't Gonna Need It,不过度设计 |
| 组合优于继承 | 用组合代替继承,更灵活 |
| 最少知识原则 | 对象只与直接朋友交互 |
| 好莱坞原则 | 框架调用你的代码,而非你调用框架(控制反转的一种形式) |
代码坏味道
坏味道是待验证的设计假设,是否重构取决于职责边界、变化原因与维护成本,而非机械匹配症状与动作。详见 代码坏味道专题。
| 坏味道 | 症状 | 解药 |
|---|---|---|
| 重复代码 | 多处相同逻辑 | 提取方法/类 |
| 过长方法 | 职责混杂、认知负担高 | 提取方法 |
| 过大类 | 类承担过多职责 | 提取类 |
| 过长参数列表 | 参数常共同传递、构成整体 | 引入参数对象 |
| 发散式变化 | 一个类因多种原因修改 | SRP 拆分 |
| 霰弹式修改 | 一个修改涉及多个类 | 移动方法/聚合行为 |
| 依恋情结 | 方法大量使用其他类的数据 | 方法搬移到数据所在的类 |
| 数据泥团 | 多个数据总是一起出现 | 提取为对象 |
| 过度耦合 | 类之间依赖过深 | 引入接口(视边界) |
| 冗余类 | 类没有存在的意义 | 删除 |
重构手法
详见 重构技术专题。
| 手法 | 说明 |
|---|---|
| 提取方法 | 将代码块提取为独立方法 |
| 提取类 | 将相关字段和方法提取为新类 |
| 内联方法 | 方法体比方法名更易懂时合并回调用方 |
| 以对象取代基本值 | 用对象包装原始类型(如 Money) |
| 以策略取代条件 | 算法需独立选择、替换或扩展时,用策略模式替换 if-else |
| 以多态取代条件 | 分支对应不同类型契约时,用多态替换 type 判断 |
| 引入参数对象 | 将多个参数封装为对象 |
| 搬移方法 | 将方法移到更合适的类 |
稳定且简单的条件分支,保留 if-else 原实现往往更直接,不必为消除分支而引入额外类与接口。