你说得对!这些设计原则听起来都很抽象、很“玄”,如果不是实际开发过系统,很难理解“到底为什么要这样设计”。
那我现在就用一个你能想象得很清楚的真实例子,帮你把这7个设计原则一一落地到具体情境里,你会一眼明白。
🧩 场景设定:你在开发一个「外卖系统」
像饿了么、美团那样的平台。我们假设你要设计一个“骑手配送子系统”。
🚴 用真实任务解释 7 个设计原则
1️⃣ 单一职责原则(SRP)
每个类只干一件事
✅ 你设计了两个类:
class Rider:def deliver_order(self): ...def update_gps(self): ...def withdraw_earnings(self): ... ❌class PaymentService:def process_withdrawal(self): ...
📌 问题:如果 Rider
也管提现,那它责任太杂 → 违反 SRP
✅ 把提现相关内容抽成 PaymentService
,每个类只管一件事。
2️⃣ 开闭原则(OCP)
增加新功能,别改老代码
用户下单时,默认是“普通配送”。
现在老板说:加个“帮我带瓶奶”的特殊配送类型。
✅ 好的,你做法是:
class DeliveryStrategy(ABC):def deliver(self): ...class NormalDelivery(DeliveryStrategy):def deliver(self): print("按原计划送")class ErrandDelivery(DeliveryStrategy):def deliver(self): print("顺便买瓶奶")# ✅ 原来用 NormalDelivery,现在只要新增一个类就行
📌 没动旧逻辑(开闭原则 ✅)
3️⃣ 接口隔离原则(ISP)
别强迫子类实现它用不到的方法
你定义了一个接口:
class RiderInterface:def deliver_food(self): ...def fly_drone(self): ... ❌
📌 大部分骑手不会飞无人机,但你却强迫所有人实现这个接口 → 违反 ISP
✅ 正确做法:
class FoodDelivery:def deliver(): ...class DroneDelivery:def fly(): ...
谁会什么功能,就实现什么接口,别搞全能型。
4️⃣ 里氏替换原则(LSP)
子类必须能安全地替代父类
你有个函数:
def assign_order(rider: Rider):rider.deliver()
但你有一个子类 LazyRider
:
class LazyRider(Rider):def deliver(self): raise Exception("我今天不想送") ❌
📌 语法没错,运行会炸。这说明 LazyRider 不能真正替代 Rider → 违反 LSP
✅ 正确做法:只有真正能送外卖的才能继承 Rider
5️⃣ 依赖倒置原则(DIP)
不依赖细节,只依赖“能力”
配送逻辑里你不直接写:
rider = AutoRider() # ❌死绑定某类
rider.deliver()
✅ 而是:
def dispatch(rider: DeliveryInterface):rider.deliver()
📌 这样你能传入自动骑手、普通骑手、临时工……
程序只关心“他能送”这个接口,而不是他是谁 → 依赖倒置 ✅
6️⃣ 合成复用原则(CRP)
能组合就别继承
你一开始写:
class SuperRider(DeliveryService):def deliver(): ...def repair_bike(): ...
📌 不要为了“多功能”就继承,而应该组合:
class RepairService:def repair(): ...class SuperRider:def __init__(self):self.repair_service = RepairService()def fix_bike(self):self.repair_service.repair()
✅ 这样如果后续要换维修流程,不改 SuperRider → 组合优于继承
7️⃣ 迪米特法则(LoD)
不该知道的事就别打听
你有一个骑手类:
class Rider:def get_bike().get_engine().check_status() ❌
📌 你“越级”访问了三层 → 太过深入别人的内部结构
✅ 正确:
rider.check_bike_status()
📌 你只知道“骑手能查车况”,不用知道车具体怎么查 → 降耦合、守住职责边界
🧠 总结表格:骑手外卖系统中 7 个设计原则怎么落地?
原则 | 在外卖系统中的例子 | 守住了什么? |
---|---|---|
✅ SRP 单一职责 | 把提现从 Rider 拆出去 | 让每个类更专注 |
✅ OCP 开闭原则 | 增加新配送方式,不动旧代码 | 提高扩展能力 |
✅ ISP 接口隔离 | 不强制 Rider 实现“飞无人机” | 让接口更贴合实际 |
✅ LSP 里氏替换 | LazyRider 会炸 → 不合适 | 保证多态安全 |
✅ DIP 依赖倒置 | 用接口注入 rider,不依赖具体类 | 解耦调用与实现 |
✅ CRP 合成复用 | 用 RepairService 而不是继承 | 优先组合、灵活替换 |
✅ LoD 迪米特法则 | 不越级访问 bike.engine | 降低耦合风险 |
如果你能记住这个「骑手外卖系统」的例子,以后看到这7个设计原则就不再抽象了,而是具体而清晰。
你要我做一个【图文并茂的思维导图 + 表格模版】帮助你记住这整套系统吗?📘