DIP的实际举例
SOLID原则。
依赖倒置原则(DIP)的核心是高层模块不应该依赖于低层模块,二者都应该依赖于抽象(接口或抽象类)
例如,随着业务的发展,订单总金额的计算规则可能需要根据不同的客户类型或促销活动进行调整。如果最初没有使用接口来抽象计算逻辑,那么可能需要直接修改具体的业务代码,这会增加代码的修改风险和维护成本。而使用接口可以方便地实现不同的计算策略,通过依赖注入等方式进行切换,提高系统的灵活性和可扩展性。
接下来我们逐步优化,把他变得满足SRP和OCP、DIP原则了。
循环累加
public class Order {private double[] productPrices;public Order(double[] productPrices) {this.productPrices = productPrices;}// 计算订单总金额的方法public double calculateTotalAmount() {double total = 0;for (double price : productPrices) {total += price;}return total;}
}
当业务发展,需要根据不同客户类型(比如普通客户、VIP 客户)和促销活动(比如满减、折扣)来调整订单总金额的计算规则时,就需要直接修改 calculateTotalAmount 方法的代码。例如,VIP 客户享受 9 折优惠,满 100 减 20 的促销活动,代码修改如下:
public class Order {private double[] productPrices;private String customerType;public Order(double[] productPrices, String customerType) {this.productPrices = productPrices;this.customerType = customerType;}// 计算订单总金额的方法,修改后变得复杂public double calculateTotalAmount() {double total = 0;for (double price : productPrices) {total += price;}if ("VIP".equals(customerType)) {total *= 0.9;}if (total >= 100) {total -= 20;}return total;}
}
这种直接修改的方式,随着业务规则的不断增加和变化,代码会变得越来越复杂和难以维护,修改一处可能会影响到其他部分的逻辑,增加了出错的风险。
抽象工厂
我们发现,订单类和计算金额的修改原因、修改速率不一样,根据SRP原则,利用抽象工厂模式,把他抽出来,如下。
// 订单类
public class Order {private double[] productPrices;private String customerType;public Order(double[] productPrices, String customerType) {this.productPrices = productPrices;this.customerType = customerType;}// 计算总金额,依赖工厂类public double calculateTotalAmount() {return OrderTotalCalculatorFactory.calculateTotal(productPrices, customerType);}
}// 订单总金额计算工厂类
public class OrderTotalCalculatorFactory {public static double calculateTotal(double[] productPrices, String customerType) {if ("Regular".equals(customerType)) {double total = 0;for (double price : productPrices) {total += price;}return total;} else if ("VIP".equals(customerType)) {double total = 0;for (double price : productPrices) {total += price;}total *= 0.9;return total;} else {double total = 0;for (double price : productPrices) {total += price;}if (total >= 100) {total -= 20;}return total;}}
}
引入抽象类
如果再有新的计费类型时,我们需要修改OrderTotalCalculatorFactory ,再添加一个if-else,然后在里面写代码,违反了OCP原则。所以我们不把具体代码写到OrderTotalCalculatorFactory 里,而是再抽一层,可以是接口,也可以不是。(这样不是说没有改动,但是改动点小了。是扩展本类,而不是修改)
但是为了专业(把相同的抽出来,作为上层),我们没有理由不写成接口。
此外如果再想加一个过期时间校验功能(我们的优惠、会员等都是有时间的),先校验,然后再计算金额。这个时候就体现出接口的好处来了。
这样就是所谓的DIP了:由原来的order订单依赖于金额计算,现在加了一个接口,二者都依赖于这个接口了。
// 订单总金额计算策略接口
public interface OrderTotalCalculator {double calculateTotal(double[] productPrices);
}// 普通客户计算策略实现类
public class RegularCustomerCalculator implements OrderTotalCalculator {@Overridepublic double calculateTotal(double[] productPrices) {double total = 0;for (double price : productPrices) {total += price;}return total;}
}// VIP客户计算策略实现类
public class VIPCustomerCalculator implements OrderTotalCalculator {@Overridepublic double calculateTotal(double[] productPrices) {double total = 0;for (double price : productPrices) {total += price;}total *= 0.9;return total;}
}// 工厂类
public class OrderTotalCalculatorFactory {public static OrderTotalCalculator createCalculator(String customerType) {if ("Regular".equals(customerType)) {return new RegularCustomerCalculator();} else if ("VIP".equals(customerType)) {return new VIPCustomerCalculator();} // 目前只有这两种情况,后续可扩展return null;}
}// 组合优于继承
public class Order {private double[] productPrices;private String customerType;private OrderTotalCalculator calculator;public Order(double[] productPrices, String customerType) {this.productPrices = productPrices;this.customerType = customerType;this.calculator = OrderTotalCalculatorFactory.createCalculator(customerType);}public double calculateTotalAmount() {return calculator.calculateTotal(productPrices);}
}
相关文章:
DIP的实际举例
SOLID原则。 依赖倒置原则(DIP)的核心是高层模块不应该依赖于低层模块,二者都应该依赖于抽象(接口或抽象类) 例如,随着业务的发展,订单总金额的计算规则可能需要根据不同的客户类型或促销活动…...
DeepSeek引领目标检测新趋势:如何通过知识蒸馏优化模型性能
目录 一、知识蒸馏是什么? 二、知识蒸馏在目标检测中的重要性 提升实时性 跨任务迁移学习 三、如何使用知识蒸馏优化目标检测? 训练教师模型 生成软标签 训练学生模型 调节温度参数 多教师蒸馏(可选) 四、案例分享 定…...
vue2.x 中父组件通过props向子组件传递数据详细解读
1. 父组件向子组件传递数据的步骤 在子组件中定义 props: 子组件通过 props 选项声明它期望接收的数据。props 可以是数组形式(简单声明)或对象形式(支持类型检查和默认值)。 在父组件中使用子组件时绑定 props&#x…...
安装PHPStudy 并搭建DVWA靶场
目录 一、PHPStudy 简介 二、DVWA 简介 三、安装 PHPStudy 四:安装 DVWA 一、PHPStudy 简介 phpstudy傻瓜式的一键启动,支持WAMP、WNMP、LAMP、LNMP,一键切换环境(nginxapahce),一键切换PHP版本(5.1-7…...
RoCBert:具有多模态对比预训练的健壮中文BERT
摘要 大规模预训练语言模型在自然语言处理(NLP)任务上取得了最新的最优结果(SOTA)。然而,这些模型容易受到对抗攻击的影响,尤其是对于表意文字语言(如中文)。 在本研究中࿰…...
【C】堆的应用1 -- 堆排序
之前学习了堆,堆的一棵以顺序结构存储的完全二叉树,堆本身又氛围大根堆和小根堆,假设以大根堆为例,由于堆顶部元素是一棵二叉树里面最大的元素,所以如果每次都取堆顶的元素,那么取出的元素就是一个降序排列…...
BGP配置华为——路径优选验证
实验拓扑 实验要求 实现通过修改AS-Path属性来影响路径选择实现通过修改Local_Preference属性来影响路径选择实现通过修改MED属性来影响路径选择实现通过修改preferred-value属性来影响路径选择 实验配置与效果 1.改名与IP配置 2.as300配置OSPF R3已经学到R2和R4的路由 3.…...
【原创】Windows11安装WSL“无法解析服务器的名称或地址”问题解决方法
原因分析 出现这个问题一开始以为WSL设置了某个服务器,但是通过运行 nslookup www.microsoft.com 出现下面的提示 PS C:\Windows\system32> nslookup www.microsoft.com 服务器: UnKnown Address: 2408:8000:XXXX:2b00:8:8:8:8非权威应答: 名称: e13678…...
【CS285】高斯策略对数概率公式的学习笔记
公式介绍 在【CS285】中提到了高斯策略对数概率公式的公式如下: log π θ ( a t ∣ s t ) − 1 2 ∥ f ( s t ) − a t ∥ Σ 2 const \log \pi_{\theta}(\mathbf{a}_t | \mathbf{s}_t) -\frac{1}{2} \left\| f(\mathbf{s}_t) - \mathbf{a}_t \right\|_{\S…...
R与RStudio简介及安装
目录 一、R与RStudio关系 二、R简介 2.1. 发展历史 2.2. R语言特点 三、安装指南 3.1 R安装指南 3.2 R studio安装指南 一、R与RStudio关系 R是统计领域广泛使用的工具,属于GNU系统的一个自由、免费、源代码开放的软件,是 用于统计计算和统计绘图…...
TTL和CMOS的区别【数电速通】
CMOS电平:电压范围在3~15V;常见电压在12V。 TTL电平:电压范围在0~5V,常见都是5V CMOS的特点:电平由电源VDD 决定,而不是外部电源电平。 COMS电路的使用注意事项 我们在使用CMOS…...
Linux红帽:RHCSA认证知识讲解(二)配置网络与登录本地远程Linux主机
Linux红帽:RHCSA认证知识讲解(二)配置网络与登录本地远程Linux主机 前言一、使用命令行(nmcli 命令)配置网络,配置主机名第一步第二步修改主机名称 二、使用图形化界面(nmtui 命令)配…...
Threejs教程一【三要素】
场景 场景是一个容器,用于容纳所有的物体、光源、相机等元素。 // 创建场景 const scene new THREE.Scene(); //修改背景颜色,颜色支持十六进制、rgb、hsl、贴图等 scene.background new THREE.Color(0x000000);相机 相机决定了渲染的结果ÿ…...
3-1 WPS JS宏工作簿的新建与保存(批量新建工作簿)学习笔记
************************************************************************************************************** 点击进入 -我要自学网-国内领先的专业视频教程学习网站 *******************************************************************************************…...
明日方舟一键端+单机+联网+安装教程+客户端apk
为了学习和研究软件内含的设计思想和原理,本人花心血和汗水带来了搭建教程!!! 教程不适于服架设,严禁服架设!!!请牢记!!! 教程仅限学习使用&…...
Redis基操
redis 存储在内存中 key-value存储 主要存储热点数据(短时间大量的访客去访问) 启动命令 redis-server.exe redis.windows.conf 客户端链接redis服务器 redis-cli.exe redis-cli.exe -h localhost -p 6379 redis-cli.exe -h localhost -p 6379 -a 123456 退出 exit 命令不区分…...
学习笔记03——《深入理解Java虚拟机(第三版)》类加载机制知识总结与面试核心要点
《深入理解Java虚拟机(第三版)》类加载机制知识总结与面试核心要点 一、章节核心脉络 核心命题:JVM如何将.class文件加载到内存并转换为运行时数据结构? 核心流程:加载 → 验证 → 准备 → 解析 → 初始化 → 使用 →…...
w227springboot旅游管理系统设计与实现
🙊作者简介:多年一线开发工作经验,原创团队,分享技术代码帮助学生学习,独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取,记得注明来意哦~🌹赠送计算机毕业设计600个选题excel文…...
漏洞文字版表述一句话版本(漏洞危害以及修复建议),通常用于漏洞通报中简洁干练【持续更新中】
漏洞文字版表述一句话版本(漏洞危害以及修复建议) SQL注入漏洞 危害描述: SQL注入漏洞允许攻击者通过构造恶意的SQL语句,绕过应用程序的安全检查,直接访问或操作数据库。这可能导致数据泄露、数据篡改、甚至数据库被删除等严重后果…...
项目——仿RabbitMQ实现消息队列
1.项目介绍 曾经在学习Linux的过程中,我们学习过阻塞队列 (BlockingQueue) 。 当时我们说阻塞队列最大的用途, 就是用来实现生产者消费者模型。 生产者消费者模型是后端开发的常用编程方式, 它存在诸多好处: 解耦合支持并发支持忙闲不均削峰…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...
【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验
Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...
Xela矩阵三轴触觉传感器的工作原理解析与应用场景
Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知,帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量,能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度,还为机器人、医疗设备和制造业的智…...
vue3 daterange正则踩坑
<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...
