基于「骑手外卖系统」串联7大设计原则
你说得对!这些设计原则听起来都很抽象、很“玄”,如果不是实际开发过系统,很难理解“到底为什么要这样设计”。
那我现在就用一个你能想象得很清楚的真实例子,帮你把这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个设计原则就不再抽象了,而是具体而清晰。
你要我做一个【图文并茂的思维导图 + 表格模版】帮助你记住这整套系统吗?📘
相关文章:
基于「骑手外卖系统」串联7大设计原则
你说得对!这些设计原则听起来都很抽象、很“玄”,如果不是实际开发过系统,很难理解“到底为什么要这样设计”。 那我现在就用一个你能想象得很清楚的真实例子,帮你把这7个设计原则一一落地到具体情境里,你会一眼明白。…...
泰迪杯特等奖案例学习资料:基于时空图卷积网络的城市排水系统水位精准重建与异常检测
(第十四届泰迪杯数据挖掘挑战赛A题特等奖案例解析) 一、案例背景与核心挑战 1.1 应用场景与行业痛点 城市排水系统(Urban Drainage Network, UDN)是城市基础设施的重要组成部分,其运行效率直接影响防洪排涝能力和水环境质量。然而,实际运维中面临以下难题: 监测数据稀…...
嵌入式Linux应用项目----智能网关
一、网关概述: Linux网关的作用在于,通过蓝牙、LoRa、串口、CAN等接口,与哪些无法连接网络的设备建立联系,将它们的数据转发至服务器。这过程中,网关充当了数据的桥梁,将下级设备所产生的数据发送至服务器。…...
C++ 中的继承
目录 前言 一、继承的概念及定义 二、基类和派生类对象赋值转换 三、继承中的作用域 四、派生类的默认成员函数 五、继承与友元 六、继承与静态成员 七、复杂的菱形继承及菱形虚拟继承 (一)单继承与多继承 (二)菱形继承 …...
【中间件】brpc_基础_用户态线程上下文
文章目录 context介绍1 简单介绍2 主要功能2.1 上下文结构定义2.2 上下文切换实现2.3 协程栈管理2.4 平台兼容性处理2.5 性能优化 3 关键代码逻辑示例3.1 上下文初始化 (bthread_make_fcontext)3.2 上下文切换 (bthread_jump_fcontext) 4 与 BRPC 其他模块的协作5 性能与稳定性…...
蟋蟀的叫声,大自然的温度计
夏夜草丛中,蟋蟀的鸣叫声此起彼伏。有趣的是,它们的叫声频率竟然与气温有关!根据图片中的公式: 气温 ( X 8 ) 5 9 \text{气温} \frac{(X 8) \times 5}{9} 气温9(X8)5 只需记录蟋蟀在 15 秒内的鸣叫次数( X X X…...
文献总结:TPAMI端到端自动驾驶综述——End-to-End Autonomous Driving: Challenges and Frontiers
端到端自动驾驶综述 1. 文章基本信息2. 背景介绍3. 端到端自动驾驶主要使用方法3. 1 模仿学习3.2 强化学习 4. 测试基准4.1 真实世界评估4.2 在线/闭环仿真测试4.3 离线/开环测试评价 5. 端到端自动驾驶面临的挑战5.1 多模态输入5.2 对视觉表征的依赖5.3 基于模型的强化学习的世…...
二极管反向恢复的定义和原理
二极管的反向恢复定义 二极管的反向恢复是指二极管从正向导通状态切换到反向阻断状态时,电流从正向变为负向并最终回到零所需的时间。具体过程如下: 正向导通:当二极管正向偏置时,电流可以顺利通过,此时二极管处于导…...
# 基于词袋模型(BoW)的猫狗图像分类实践
基于词袋模型(BoW)的猫狗图像分类实践 在计算机视觉领域,图像分类是一项基础且重要的任务。本文将介绍如何使用词袋模型(Bag of Words, BoW)结合支持向量机(SVM)实现猫狗图像分类。通过详细的代…...
Vscode+git笔记
1.U是untracked m是modify modified修改了的。 2.check out 查看观察 3 status changed 暂存区 4.fetch v 取来拿来 5.orangion 起源代表远程分支 git checkout就是可以理解为进入的意思。...
生成式 AI 的未来
在人类文明的长河中,技术革命始终是推动社会跃迁的核心引擎。从蒸汽机解放双手,到电力点亮黑夜,再到互联网编织全球神经网络,每一次技术浪潮都在重塑人类的生产方式与认知边界。而今天,生成式人工智能(Generative AI)正以一种前所未有的姿态登上历史舞台——它不再局限于…...
进程间通信(IPC)
进程间通信(IPC)是操作系统中非常重要且基础的概念,涉及到不同进程之间如何交换数据和同步操作。下面我会一个一个地详细讲解这几种常见的IPC方式:管道(包含匿名管道和有名管道)、消息队列、共享内存、信号量、Socket通信,内容尽量用通俗易懂的语言,并结合具体原理、优…...
C语言奇幻指南:宏、头文件与变量的秘密世界
🌟 C语言奇幻指南:宏、头文件与变量的秘密世界 🌟 一、写一个“比小”宏:三目运算符的魔法 目标:定义一个宏,返回两个参数中较小的值。 代码: #define MIN(a, b) ((a) < (b) ? (a) : (b))…...
【开源免费】二维码批量识别-未来之窗——C#-仙盟创梦IDE
二维码批量识别工具,借助先进图像识别技术,能快速准确读取大量二维码信息。适用于物流与供应链管理,如库存盘点和货物追踪;可用于资产管理,像固定资产盘点与设备巡检;还能助力数据收集与市场调研࿰…...
n8n工作流自动化平台的实操:解决中文乱码
解决问题: 通过ftp读取中文内容的文件,会存在乱码,如下图: 解决方案 1.详见《安装 iconv-lite》 2.在code节点,写如下代码: const iconv require(iconv-lite);const items $input.all(); items.forEa…...
MCP 探索:MCP 集成的相关网站 Smithery、PulseMCP 等
简简单单 Online zuozuo :本心、输入输出、结果 文章目录 MCP 探索:MCP 集成的相关网站 Smithery、PulseMCP 等前言一、MCP 集成基础二、利用热门资源平台集成三、集成常见 MCP 服务四、管理集成的 MCP 能力五、集成示例借鉴六、数据交互与安全管理MCP 探索:MCP 集成的相关网…...
linux的时间轮
时间轮:高效管理海量定时任务的利器 1. 引言:为什么需要时间轮? 在许多应用场景中,我们都需要管理大量的定时任务,例如: 网络连接的超时检测。分布式系统中的心跳检测。缓存条目的过期淘汰。需要延迟执行…...
《操作系统真象还原》第十二章(2)——进一步完善内核
文章目录 前言可变参数的原理实现系统调用write更新syscall.h更新syscall.c更新syscall-init.c 实现printf编写stdio.h编写stdio.c 第一次测试main.cmakefile结果截图 完善printf修改main.c 结语 前言 上部分链接:《操作系统真象还原》第十二章(1&#…...
MIT6.S081-lab8前置
MIT6.S081-lab8前置 注:本部分除了文件系统还包含了调度的内容。 调度 调度涉及到保存寄存器,恢复寄存器,就这一点而言,和我们的 trap 很像,但是实际上,我们实现并不是复用了 trap 的逻辑,我…...
Java从入门到精通 - Java语法
Java 语法 此笔记参考黑马教程,仅学习使用,如有侵权,联系必删 文章目录 Java 语法01 变量详解1. 变量里的数据在计算机中的存储原理1.1 二进制1.2 十进制转二进制的算法1.3 计算机中表示数据的最小单元总结1.4 字符在计算机中是如何存储的呢…...
【CF】Day50——Codeforces Round 960 (Div. 2) BCD
B. Array Craft 题目: 思路: 有点意思的构造 首先题目告诉我们 y < x,这是一个重要的条件 我们先来考虑简单情况,假如可以放0进去,那么我们只需要在 y ~ x 之间全放 1 ,其余都是 0 即可,但…...
MySQL 日期加减函数详解
MySQL 日期加减函数详解 1. DATE_ADD 函数 基本语法 DATE_ADD(date, INTERVAL expr unit)功能 在指定日期/时间上添加一个时间间隔 参数说明 date:要处理的日期/时间值(可以是DATE, DATETIME或TIMESTAMP类型)expr:要添加的间…...
NV189NV195美光固态闪存NV197NV199
NV189NV195美光固态闪存NV197NV199 在存储技术持续迭代的2025年,美光固态闪存NV189、NV195、NV197、NV199系列凭借其差异化的性能定位,正在重新定义数据存储的边界。本文将从技术参数、场景适配、行业价值等维度,为不同领域的专业人士提供深度…...
C语言-回调函数
回调函数 通过函数指针调用函数,而这个被调用的函数称为回调函数 回调函数是C语言中一种强大的机制,允许将函数作为参数传递给其他函数,从而在特定时机由后者调用。它的核心在于函数指针的使用 以下是回调函数的使用例子 先创建好一个函数…...
启发式算法-蚁群算法
蚁群算法是模拟蚂蚁觅食行为的仿生优化算法,原理是信息素的正反馈机制,蚂蚁通过释放信息素来引导同伴找到最短路径。把问题的元素抽象为多条路径,每次迭代时为每只蚂蚁构建一个解决方案,该解决方案对应一条完整的路径,…...
DeepSeek与MySQL:开启数据智能新时代
目录 一、引言:技术融合的力量二、DeepSeek 与 MySQL:技术基石2.1 DeepSeek 技术探秘2.2 MySQL 数据库深度解析 三、DeepSeek 与 MySQL 集成:从理论到实践3.1 集成原理剖析3.2 集成步骤详解 四、应用案例:实战中的价值体现4.1 电商…...
Modbus 通讯协议(超详细,简单易懂)
目录 一、协议中的寄存器定义 二、协议概述 三、使用串口的Modbus 报文帧 编辑 3.1、Modbus ASCII 模式 3.2、Modbus RTU 模式 3.3、功能码概要 3.4、Modbus 报文分析 四、什么是RS-485 RS-232? 一、协议中的寄存器定义 阅读 Modbus 协议时会发现它的概念别扭…...
单细胞测序试验设计赏析(一)
单细胞测序试验设计赏析(一) 单细胞测序试验设计中,单细胞测序技术通常会结合其它的技术来共同说明问题,或者结合年龄、性别等临床数据,进行分层分析说明问题以下以发表文章来进行一定的分析。 Single-cell RNA seque…...
ES6入门---第二单元 模块三:对象新增、
一:对象简洁语法: 1、变量简洁 <script>let name Strive;let age 18;let json {name, //name:name,age //age:age};console.log(json);</script> 2、函数简洁 let json {name, //name:name,age, //age:age/* showA:functi…...
多元随机变量协方差矩阵
主要记录多元随机变量数字特征相关内容。 关键词:多元统计分析 二元随机变量(X, Y) 说明:可以理解变量中的 X为身高、Y为体重 总体协方差 σ X Y c o v ( X , Y ) E [ ( X − μ X ) ( Y − μ Y ) ] E ( X Y ) − μ X μ Y \sigma_{XY}cov(X, Y)E[…...
计算机网络-同等学力计算机综合真题及答案
计算机网络-同等学力计算机综合真题及答案 (2003-2024) 2003 年网络 第二部分 计算机网络(共 30 分) (因大纲变动因此 2004 年真题仅附真题,不作解析。) 一、填空题(共 10 分&#…...
[案例二] 菜单条制作(Menuscript)与工具条制作(Toolbar)
最近五一正好毕业论文盲审,抽时间研究一下菜单条制作(Menuscript)与工具条制作(Toolbar)的制作,在NX二次开发中唐康林老师已经讲的很详细了,在这里只对视频中的内容进行总结,并且根据自己的想法进行补充。在里海博主的直播教学中发现一个很有趣的NX图标工具,本人大概做了一…...
bellard.org : QuickJS 如何使用 qjs 执行 js 脚本
参阅上一篇:Fabrice Bellard(个人网站:bellard.org)介绍 Fabrice Bellard(个人网站:bellard.org)是计算机领域最具影响力的程序员之一,其贡献跨越多个技术领域并持续推动开…...
计组复习笔记 3
前言 继续做例题。昨天做到第一个就把我难住了。可恶。 4.1 地址码越长,操作码越短。因为两者加起来是指令字,指令字的大小一般是固定的。扩展编码按照操作码从短到长进行编码。算了先放一下。我先看一下别的复习资料。等会儿再看这个题。 鼓励自己 …...
GCD 深入解析:从使用到底层实现
前言 Grand Central Dispatch (GCD) 是 Apple 基于 C 语言开发的一套完整的并发编程框架。它不仅仅是一个简单的线程管理工具,而是一个高度优化的并发编程解决方案。GCD 的设计理念是将并发编程的复杂性封装在框架内部,为开发者提供简单易用的接口。本文…...
JavaScript中的AES加密与解密:原理、代码与实战
前言 关于有js加密、js解密,js业务相关,找jsjiami官网站长v。 另外前段时间做了个单子跑单了,出售TEMU助手。eller点kuajingmaihuo点com的全自动化助手,可以批量合规,批量实拍图,批量资质上传等。 一、A…...
计算机组成原理实验(7) 堆指令部件模块实验
实验七 堆指令部件模块实验 一、实验目的 1、掌握指令部件的组成方式。 2、熟悉指令寄存器的打入操作,PC计数器的设置和加1操作,理解跳转指令的实现过程。 二、实验要求 按照实验步骤完成实验项目,掌握数据打入指令寄存器IR1、PC计数器的…...
Windows系统下Node.js环境部署指南:使用nvm管理多版本
Windows系统下Node.js环境部署指南:使用nvm管理多版本 一、Node.js介绍二、为什么需要nvm?三、安装前的准备工作1. 本次环境说明2. 卸载现有Node.js(如有) 三、nvm-windows安装步骤1. 下载安装包2. 安装过程3. 验证安装 四、使用n…...
数据结构*队列
队列 什么是队列 是一种线性的数据结构,和栈不同,队列遵循“先进先出”的原则。如下图所示: 在集合框架中我们可以看到LinkedList类继承了Queue类(队列)。 普通队列(Queue) Queue中的方法 …...
C语言蓝桥杯真题代码
以下是不同届蓝桥杯C语言真题代码示例,供参考: 第十三届蓝桥杯省赛 C语言大学B组 真题:卡片 题目:小蓝有很多数字卡片,每张卡片上都是数字1-9。他想拼出1到n的数列,每张卡片只能用一次,求最大的…...
Sharding-JDBC分库分表中的热点数据分布不均匀问题及解决方案
引言 在现代分布式应用中,使用Sharding-JDBC进行数据库的分库分表是提高系统性能和扩展性的常见策略。然而,在实际应用中,某些特定的数据(如最新订单、热门商品等)可能会成为“热点”,导致这些部分的数据处…...
Dagster中的Ops与Assets:数据管道构建的两种选择
Dagster是一个强大的数据编排平台,它提供了多种工具来帮助数据工程师构建可靠的数据管道。在Dagster中,Ops和Assets是两种核心概念,用于定义数据处理逻辑。本文将全面介绍Ops的概念、特性及其使用方法,特别补充了Op上下文和Op工厂…...
thonny提示自动补全功能
THONNY IDE 自动补全功能配置 在 Thonny IDE 中启用和优化自动补全功能可以显著提升编程体验。为了确保该功能正常工作,需要确认几个设置选项。 配置自动补全 Thonyy IDE 的自动补全默认情况下是开启的。如果发现自动补全未按预期运行,可以通过调整首选…...
PyTorch_阿达玛积
阿达玛积指的是矩阵对应位置的元素相乘,可以使用乘号运算符,也可以使用mul函数来完成计算。 代码 import torch import numpy as np # 1. 使用 mul 函数 def test01():data1 torch.tensor([[1, 2], [3, 4]])data2 torch.tensor([[5, 6], [7, 8]])dat…...
蓝桥杯 摆动序列
摆动序列 原题目链接 题目描述 如果一个序列的奇数项都比前一项大,偶数项都比前一项小,则称为一个摆动序列。 即对于任意整数 i(i ≥ 1)满足: a₂ᵢ < a₂ᵢ₋₁,a₂ᵢ₊₁ > a₂ᵢ 小明想知道&…...
AI 与生物技术的融合:开启精准医疗的新纪元
在科技飞速发展的今天,人工智能(AI)与生物技术的融合正在成为推动医疗领域变革的重要力量。精准医疗作为现代医学的重要发展方向,旨在通过深入了解个体的基因信息、生理特征和生活方式,为患者提供个性化的治疗方案。AI…...
三、shell脚本--运算符与表达式:让脚本学会“思考”
一、算术运算符:加减乘除取模 在我们写shell脚本时,做点基本的数学运算还是经常需要的。常用的算术运算符跟我们平时学的一样: : 加- : 减* : 乘 (小提示:有时候在某些命令里可能需要写成 \*)/ : 除 (在 Shell 里通常是取整数部分…...
c++ 指针参数传递的深层原理
指针参数传递的深层原理 理解为什么可以修改指针指向的内容但不能直接修改指针本身,需要深入理解指针在内存中的表示方式和函数参数传递机制。 1. 指针的内存表示 指针本质上是一个变量,它存储的是另一个变量的内存地址。在内存中: 假设有…...
【查看.ipynp 文件】
目录 如何打开 .ipynb 文件? 如果确实是 .ipynp 文件: .ipynp 并不是常见的 Jupyter Notebook 文件格式。通常,Jupyter Notebook 文件的扩展名是 .ipynb(即 Interactive Python Notebook)。如果你遇到的是 .ipynb 文…...
C++ 简单工厂模式详解
简单工厂模式(Simple Factory Pattern)是最简单的工厂模式,它不属于GoF 23种设计模式,但它是工厂方法模式和抽象工厂模式的基础。 概念解析 简单工厂模式的核心思想是: 将对象的创建逻辑集中在一个工厂类中 客户端不…...