一. 6大原则速查对比
| 原则 | 核心概念 | 一句话记忆 | 违反的典型症状 |
|---|---|---|---|
| 单一职责 | 类/模块只负责一个功能领域 | 专人专事 | 一个类修改理由太多 |
| 开闭原则 | 扩展新功能时不改原有代码 | 添新不改旧 | 每加需求都要改旧类 |
| 里氏替换 | 子类必须能完全替代父类 | 换子不报错 | 子类重写后行为异常 |
| 依赖倒置 | 依赖抽象接口而非具体实现 | 面向接口 | 代码里全是new具体类 |
| 接口隔离 | 大接口拆分为小接口 | 接口瘦身 | 实现类有很多空方法 |
| 迪米特法则 | 只与直接合作对象交互 | 别管闲事 | 链式调用a.b.c.d() |
原则关系图
┌─────────────┐
│ 开闭原则 │ ← 终极目标:灵活扩展
│ (顶层设计) │
└──────┬──────┘
│
┌─────────┼─────────┐
▼ ▼ ▼
┌───────┐ ┌───────┐ ┌───────┐
│ 单一职责│ │ 里氏替换│ │ 依赖倒置│ ← 三大支撑
│ (内聚) │ │ (继承) │ │ (耦合) │
└───────┘ └───────┘ └───┬───┘
│
┌───┴───┐
▼ ▼
┌───────┐ ┌───────┐
│ 接口隔离│ │ 迪米特法则│ ← 具体手段
│ (接口) │ │ (交互) │
└───────┘ └───────┘
二. 使用场景与实例
1. 单一职责原则 (SRP)
| 维度 | 内容 |
|---|---|
| 触发场景 | 一个类代码超过300行;修改时要改多个地方 |
| 典型应用 | 分层架构(Controller/Service/DAO分离) |
| 生活类比 | 餐厅分工:服务员点菜、厨师做菜、收银结账 |
实例:电商订单系统
-
❌ 错误:
OrderManager处理订单+支付+物流+发邮件 -
✅ 正确:
OrderService+PaymentService+LogisticsService+NotificationService
2. 开闭原则 (OCP)
| 维度 | 内容 |
|---|---|
| 触发场景 | 业务规则频繁变化;需要支持多种算法/策略 |
| 典型应用 | 策略模式、插件架构、规则引擎 |
| 生活类比 | 手机APP:更新功能不用换手机,装新APP即可 |
实例:促销活动系统
| 场景 | 实现方式 |
|---|---|
| 双11满减 | 新增Double11Strategy类 |
| 618折扣 | 新增Discount618Strategy类 |
| 会员价 | 新增MemberPriceStrategy类 |
| 共同点 | 都实现PromotionStrategy接口,原有代码零修改 |
3. 里氏替换原则 (LSP)
| 维度 | 内容 |
|---|---|
| 触发场景 | 使用继承关系时;多态调用时 |
| 典型应用 | 集合框架、日志框架(可替换实现) |
| 生活类比 | USB接口:U盘、鼠标、键盘都能插,电脑不用区分 |
实例:权限系统
-
❌ 错误:
AdminUser extends User,但AdminUser禁用了普通用户的某些功能 -
✅ 正确:
User和Admin都实现Principal接口,各自完整实现,互不干扰
4. 依赖倒置原则 (DIP)
| 维度 | 内容 |
|---|---|
| 触发场景 | 需要切换底层实现;需要单元测试 |
| 典型应用 | Spring依赖注入、Repository模式、Mock测试 |
| 生活类比 | 电源插座:电器依赖插座接口,不依赖具体电厂 |
实例:数据访问层
| 层级 | 依赖关系 |
|---|---|
| 业务层 | ← 依赖 UserRepository 接口 |
| 接口层 | UserRepository 定义方法 |
| 实现层 | MySQLUserRepository / MongoUserRepository / RedisUserRepository |
切换数据库:改配置即可,业务代码不动
5. 接口隔离原则 (ISP)
| 维度 | 内容 |
|---|---|
| 触发场景 | 接口方法太多;不同实现者需求不同 |
| 典型应用 | 驱动程序接口、回调接口拆分 |
| 生活类比 | Swiss军刀 vs 专用工具箱:专业场景用专用工具 |
实例:打印机驱动
-
❌ 错误接口:
Printer包含打印+扫描+传真+复印 -
✅ 拆分后:
-
Printable→ 普通打印机实现 -
Scannable→ 扫描仪实现 -
Faxable→ 传真机实现 -
Copiable→ 复合机实现多个接口
-
6. 迪米特法则 (LoD)
| 维度 | 内容 |
|---|---|
| 触发场景 | 对象间调用链过长;需要降低耦合度 |
| 典型应用 | 外观模式、中介者模式、DTO封装 |
| 生活类比 | 办事找窗口:不直接找后台科室,由窗口统一协调 |
实例:电商下单流程
-
❌ 违反:
OrderController→ 调OrderService→ 调InventoryService→ 调WarehouseService→ 调StockDao -
✅ 遵守:
OrderController只调OrderService,库存检查由OrderService内部协调,对外隐藏细节
三. 综合决策表
| 遇到这个问题 | 使用这个原则 | 典型解决方案 |
|---|---|---|
| 类太大,改不动 | SRP | 拆分成多个小类 |
| 加功能要改旧代码 | OCP | 抽象策略+工厂模式 |
| 继承后行为异常 | LSP | 用组合代替继承 |
| 换组件要改很多代码 | DIP | 依赖注入+接口 |
| 实现接口要写空方法 | ISP | 拆分大接口 |
| 调用链太长,调试困难 | LoD | 外观模式/封装内部 |
一句话总结
SRP 管"分工",OCP 管"扩展",LSP 管"继承",DIP 管"依赖",ISP 管"接口",LoD 管"交互" ------ 六者合力,实现高内聚、低耦合的设计目标。