当前位置: 首页 > news >正文

设计模式—依赖倒置原则(DIP)

1.概念

依赖倒置原则(Dependence Inversion Principle)是程序要依赖于抽象接口,不要依赖于具体实现。简单的说就是要求对抽象进行编程,不要对实现进行编程,这样就降低了客户与实现模块间的耦合。

通俗的讲:

  1. 要面向抽象编程,而不是面向细节编程;

  2. 高层模块不应该依赖底层模块,二者应该通过抽象依赖,而不是依赖细节;

  3. 抽象不应该依赖于具体,具体应该依赖于抽象。

2.案例分析

需求:我们要开发一套自动驾驶系统,只要在汽车上安装该系统就可以实现自动驾驶,该系统目前只支持在福特和本田车上使用。

优化前版本(不满足依赖倒置原则):

/// <summary>/// 福特车/// </summary>public class FordCar{public void Run(){Console.WriteLine("福特开始启动了");}public void Turn(){Console.WriteLine("福特开始转弯了");}public void Stop(){Console.WriteLine("福特开始停车了");}}/// <summary>/// 本田车/// </summary>public class HondaCar{public void Run(){Console.WriteLine("本田开始启动了");}public void Turn(){Console.WriteLine("本田开始转弯了");}public void Stop(){Console.WriteLine("本田开始停车了");}}/// <summary>/// 自动驾驶/// </summary>public class AutoSystem{private HondaCar hcar = new HondaCar();private FordCar fcar = new FordCar();private CarType type;public AutoSystem(CarType type){this.type = type;}/// <summary>/// 启动/// </summary>public void RunCar(){if (type == CarType.Ford){fcar.Run();}else{hcar.Run();}}/// <summary>/// 转弯/// </summary>public void TurnCar(){if (type == CarType.Ford){fcar.Turn();}else{hcar.Turn();}}/// <summary>/// 停车/// </summary>public void StopCar(){if (type == CarType.Ford){fcar.Stop();}else{hcar.Stop();}}public enum CarType : int{[Description("福特车")]Ford = 0,[Description("本田车")]Honda = 1,};}{//DIP:依赖倒置原则//福特车AutoSystem fordAutoSystem = new AutoSystem(CarType.Ford);fordAutoSystem.RunCar();fordAutoSystem.TurnCar();fordAutoSystem.StopCar();//本田车AutoSystem hondaAutoSystem = new AutoSystem(CarType.Honda);hondaAutoSystem.RunCar();hondaAutoSystem.TurnCar();hondaAutoSystem.StopCar();}

代码分析:

上面的程序确实能够实现针对Ford和Honda车的无人驾驶,但是在实际的生成场景中需求是不断变化的,比如我们现在又增加了一个新的合作伙伴:宝马车,那我们就需要新定义一个宝马车的实现类,以及对应的枚举CarType和上层的AutoSystem类都需要跟着修改,当随着越来越多的车企加入我们,那我们当前的设计就会变得僵化、脆弱。

如何优化?

导致上面所述问题的一个原因是:含有高层策略的utoSystem模块,依赖于它所控制的低层的具体细节的模块:HondaCar和FordCar。如果我们能够找到一种方法使AutoSystem模块独立于它所控制的具体细节,那么我们就可以自由地复用它了。我们就可以用这个模块来生成其它的程序,使得系统能够用在需要的汽车上。毋庸置疑那就该我们的依赖倒置原则出场了。

优化后的版本(满足依赖倒置原则):

/// <summary>/// 接口层/// </summary>public interface ICar{void Run();void Turn();void Stop();}/// <summary>/// 福特车/// </summary>public class FordCarDIP : ICar{public void Run(){Console.WriteLine("福特开始启动了");}public void Turn(){Console.WriteLine("福特开始转弯了");}public void Stop(){Console.WriteLine("福特开始停车了");}}/// <summary>/// 本田车/// </summary>public class HondaCarDIP : ICar{public void Run(){Console.WriteLine("本田开始启动了");}public void Turn(){Console.WriteLine("本田开始转弯了");}public void Stop(){Console.WriteLine("本田开始停车了");}}/// <summary>/// 自动驾驶/// </summary>public class AutoSystemDIP{private ICar icar;public AutoSystemDIP(ICar icar){this.icar = icar;}/// <summary>/// 启动/// </summary>public void RunCar(){icar.Run();}/// <summary>/// 拐弯/// </summary>public void TurnCar(){icar.Turn();}/// <summary>/// 停车/// </summary>public void StopCar(){icar.Stop();}}{//DIP:依赖倒置原则//福特车ICar car = new FordCarDIP();AutoSystemDIP fordAutoSystem = new AutoSystemDIP(car);fordAutoSystem.RunCar();fordAutoSystem.TurnCar();fordAutoSystem.StopCar();//本田车car = new HondaCarDIP();AutoSystemDIP hondaAutoSystem = new AutoSystemDIP(car);hondaAutoSystem.RunCar();hondaAutoSystem.TurnCar();hondaAutoSystem.StopCar();}

代码分析:

AutoSystem系统依赖于ICar 这个抽象,而与具体的实现细节HondaCar、FordCar无关,所以实现细节的变化不会影响AutoSystem。对于实现细节只要实现ICar 即可,即实现细节依赖于ICar 抽象。

3.优缺点

优点:

  1. 降低类与类之间的耦合性;

  2. 增强系统的稳定性;

  3. 提高代码的可读性和维护性;

  4. 降低修改代码带来的风险;

缺点:

除了抽象难度大点、需要对功能业务理解透彻以外,几乎无缺点,依赖倒置还是我们开发中使用比较频繁的一个原则。

相关文章:

设计模式—依赖倒置原则(DIP)

1.概念 依赖倒置原则&#xff08;Dependence Inversion Principle&#xff09;是程序要依赖于抽象接口&#xff0c;不要依赖于具体实现。简单的说就是要求对抽象进行编程&#xff0c;不要对实现进行编程&#xff0c;这样就降低了客户与实现模块间的耦合。 通俗的讲&#xff1…...

windows下docker环境搭建与运行实战

背景 学习docker使用&#xff0c;需要环境&#xff0c;今天主要的目标是在windows环境下安装docker环境。 为什么要这么搞&#xff0c;主要是企业内部服务器&#xff0c;都是跟公网隔离的&#xff0c;没有访问公网权限&#xff0c;所以镜像什么的&#xff0c;从公网拉取完全没…...

c# EF框架的增删改查操作

查询 /// <summary>/// 查询/// </summary>private void SQLLoad(){//linq查询&#xff0c;方法一//var UserInfoList from u in db.UserInfo//给个变量u&#xff0c;用来接收查询结果对象//select u;//查询结果对象 //db.UserInfo.Find(1);//依据主键查询,方法二…...

Element-UI Upload 手动上传文件的实现与优化

文章目录 引言第一部分&#xff1a;Element-UI Upload 基本用法1.1 安装 Element-UI1.2 使用 <el-upload> 组件 第二部分&#xff1a;手动上传文件2.1 手动触发上传2.2 手动上传时的文件处理 第三部分&#xff1a;性能优化3.1 并发上传3.2 文件上传限制 结语 &#x1f38…...

持续集成部署-k8s-配置与存储-存储类:动态创建NFS-PV案例

动态创建NFS-PV案例 1. 前置条件2. StorageClass 存储类的概念和使用3. RBAC 配置4. storageClass 配置5. 创建应用&#xff0c;测试 PVC 的自动配置6. 解决 PVC 为 Pending 状态问题7. 单独测试自动创建 PVC 1. 前置条件 这里使用 NFS 存储的方式&#xff0c;来演示动态创建 …...

jar包不挂断地运行命令

nohup java -jar wpfx.jar com.xiaobai.wpfx.WpfxApplication > ./demo.log 2>&1 &这段命令主要是用来在后台运行一个Java应用程序&#xff0c;并将输出日志写入到demo.log文件中。下面是每个参数的解释&#xff1a; nohup&#xff1a;表示不挂断地运行命令&…...

人工智能-优化算法和深度学习

优化和深度学习 对于深度学习问题&#xff0c;我们通常会先定义损失函数。一旦我们有了损失函数&#xff0c;我们就可以使用优化算法来尝试最小化损失。在优化中&#xff0c;损失函数通常被称为优化问题的目标函数。按照传统惯例&#xff0c;大多数优化算法都关注的是最小化。…...

【开源】基于Vue和SpringBoot的食品生产管理系统

项目编号&#xff1a; S 044 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S044&#xff0c;文末获取源码。} 项目编号&#xff1a;S044&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 加工厂管理模块2.2 客户管理模块2.3…...

洛谷P1049装箱问题 ————递归+剪枝+回溯

没没没没没没没没没错&#xff0c;又是一道简单的递归&#xff0c;只不过加了剪枝&#xff0c;我已经不想再多说&#xff0c;这道题写了一开始写了普通深搜&#xff0c;然后tle了一个点&#xff0c;后面改成剪枝&#xff0c;就ac了&#xff0c;虽然数据很水&#xff0c;但是不妨…...

C++通讯录管理系统

目录 系统需求 1、 创建项目 2、 菜单功能设计 3、 退出功能设计 4、 添加联系人功能设计 4.1 设计联系人结构体 4.2 设计通讯录结构体 4.3 在main函数中创建通讯录 4.4 封装添加联系人函数 4.5 添加联系人功能测试 5、 显示联系人功能设计 5.1 封装显示…...

Windows安装Python环境(V3.6)

文章目录 一&#xff1a;进入网址&#xff1a;https://www.python.org/downloads/ 二&#xff1a;执行安装包 默认C盘&#xff0c;选择自定义安装目录 记得勾选add python path 下面文件夹最好不要有 . 等特殊符号 可以创建 python36 如果安装失败Option可以选默认的&#x…...

python 如何调用GPT系列的api接口,实现想要的功能

目录 问题描述&#xff1a; 问题解决&#xff1a; 问题描述&#xff1a; 随着各种LLMs (Large Language Models&#xff09;的出现&#xff0c;如何调用各种LLMs的api成为了经常会遇见的问题。 问题解决&#xff1a; 下面仅以生成给定sentence的复述句为例&#xff0c;说明…...

JS动态参数arguments与剩余参数

arguments是函数内部内置的伪数组变量&#xff0c;它包含了调用函数时传入的所以实参 让我为大家介绍一下arguments吧 平时我们获取实参&#xff1a; function fun(a, b) {console.log(a) //1console.log(b) //2}fun(1, 2)接下来我们来使用一下arguments动态获取实参 function …...

使用ListenableFuture进行异步任务执行并进行线程切换

文章目录 一、前言二、关键代码三、参考链接 一、前言 在程序中会经常需要做一些异步任务&#xff0c;但是由于部分操作其实很简单&#xff0c;仅仅是短暂的进行异步操作&#xff0c;然后在结果成功或失败的时候切换回主线程进行下一步处理&#xff0c;这期间不能阻塞主线程。…...

C#,数值计算——插值和外推,RBF_fn 与 RBF_gauss 的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { public interface RBF_fn { double rbf(double r); } } ---------------------------------------------- using System; namespace Legalsoft.Truffer { public class RBF_gauss : RBF…...

Java8实战-总结49

Java8实战-总结49 CompletableFuture&#xff1a;组合式异步编程对多个异步任务进行流水线操作构造同步和异步操作将两个 CompletableFuture 对象整合起来&#xff0c;无论它们是否存在依赖 CompletableFuture&#xff1a;组合式异步编程 对多个异步任务进行流水线操作 构造同…...

云匣子 FastJson反序列化RCE漏洞复现

0x01 产品简介 云匣子是租户连接云资源的安全管理工具&#xff0c;帮助云租户更加安全、精细的管理云上的虚拟机、数据库等资源。 云安宝结合多年的运维和安全实践&#xff0c;将云上的运维和安全有机结合&#xff0c;实现对运维过程的事前规划、事中控制和 事后审计。在此之上…...

全程云OA SQL注入漏洞复现

0x01 产品简介 全程云OA为企业提供日常办公管理、公文管理、工作请示、汇报、档案、知识体系、预算控制等26个功能&#xff0c;超过100多个子模块。为企业内部提供高效、畅通的信息渠道&#xff0c;同时也能大力推动公司信息系统发展&#xff0c;提高企业的办公自动化程度和综合…...

IDEA DeBug

文章目录 01_Debug简介和意义02_IDEA中的Debug步骤03_跳转到当前代码执行的行04_步过调试的使用05_步入调试的使用06_强制步入调试的使用07_步出调试的使用08_回退断点调试的使用09_运行到光标处10_计算表达式11_条件断点12_多线程调试 01_Debug简介和意义 什么是程序DeBug&am…...

本地部署 ComfyUI

本地部署 ComfyUI ComfyUI 介绍ComfyUI Github 地址部署 ComfyUI配置模型地址 or 下载模型启动 ComfyUI访问 ComfyUI使用技巧页面底部显示图片预览改变连接线的格式配置 prompt 自动补全 安装 ComfyUI-Manager安装 AIGODLIKE-COMFYUI-TRANSLATION安装 ComfyUI-Custom-Scripts安…...

千问3.5-2B快速上手:网页端四步操作(上传→提问→设置→获取)详解

千问3.5-2B快速上手&#xff1a;网页端四步操作&#xff08;上传→提问→设置→获取&#xff09;详解 1. 开篇&#xff1a;认识千问3.5-2B 千问3.5-2B是Qwen系列中的一款轻量级视觉语言模型&#xff0c;它能像人类一样"看"图片并回答相关问题。想象一下&#xff0c…...

【大模型工程化核心基建】:3大血缘追踪实战框架,90%团队尚未部署的模型治理关键能力

第一章&#xff1a;大模型工程化中的模型血缘追踪 2026奇点智能技术大会(https://ml-summit.org) 在大规模语言模型的持续迭代与部署过程中&#xff0c;模型版本、训练数据集、微调脚本、超参配置及评估指标之间形成复杂的依赖网络。缺乏系统化的血缘追踪能力&#xff0c;将导…...

DDD难落地?就让AI干吧! - cleanddd-skills介绍粟

AI训练存储选型的演进路线 第一阶段&#xff1a;单机直连时代 早期的深度学习数据集较小&#xff0c;模型训练通常在单台服务器或单张GPU卡上完成。此时直接将数据存储在训练机器的本地NVMe SSD/HDD上。 其优势在于IO延迟最低&#xff0c;吞吐量极高&#xff0c;也就是“数据离…...

别只盯着IV曲线!用Silvaco TCAD深挖电阻仿真的5个隐藏玩法

别只盯着IV曲线&#xff01;用Silvaco TCAD深挖电阻仿真的5个隐藏玩法 在半导体器件仿真领域&#xff0c;电阻模型常被视为入门级的"Hello World"案例。但正是这种看似简单的结构&#xff0c;往往蕴含着最基础却最容易被忽视的物理本质。本文将带你跳出标准例程的框…...

鸿蒙6的**星盾安全(StarShield)技术

鸿蒙6的星盾安全&#xff08;StarShield&#xff09;**** 是当前移动与全场景OS领域最体系化、最主动、最贴近用户真实场景的安全架构之一。它不是简单的“补丁式安全”&#xff0c;而是从芯片→内核→AI→用户场景的全链路纵深防御&#xff0c;核心价值在于&#xff1a;把安全…...

5步掌握BepInEx插件管理:从依赖混乱到和谐共存的完整指南

5步掌握BepInEx插件管理&#xff1a;从依赖混乱到和谐共存的完整指南 【免费下载链接】BepInEx Unity / XNA game patcher and plugin framework 项目地址: https://gitcode.com/GitHub_Trending/be/BepInEx BepInEx是Unity Mono、IL2CPP和.NET框架游戏的强大插件框架&a…...

Qwen3智能字幕系统效果展示:直播回放语音→低延迟字幕流实时生成

Qwen3智能字幕系统效果展示&#xff1a;直播回放语音→低延迟字幕流实时生成 想象一下这个场景&#xff1a;一场精彩的直播刚刚结束&#xff0c;你迫不及待地想回顾其中的高光片段&#xff0c;或者需要快速整理出会议的核心内容。面对长达数小时的视频&#xff0c;手动添加字幕…...

纵轴套零件的工艺规程及钻、攻6-M5-7H螺纹的工装夹具设计(设计说明书+CAD图纸+工序卡+过程卡)

纵轴套零件作为机械传动系统中的关键部件&#xff0c;其加工质量直接影响设备运行的稳定性。设计合理的工艺规程与专用工装夹具&#xff0c;是确保零件加工精度、提升生产效率的核心环节。本文围绕纵轴套零件的工艺设计展开&#xff0c;重点解析钻、攻6-M5-7H螺纹的工装方案&am…...

人脸识别模型效果展示:Retinaface+CurricularFace实测案例分享

人脸识别模型效果展示&#xff1a;RetinafaceCurricularFace实测案例分享 1. 模型效果概览 RetinafaceCurricularFace组合模型在人脸识别领域展现出卓越性能。这套方案通过Retinaface实现高精度人脸检测&#xff0c;再结合CurricularFace进行深度特征提取与比对&#xff0c;在…...

终极指南:如何用Sunshine搭建免费游戏串流服务器,让任何设备畅玩PC大作

终极指南&#xff1a;如何用Sunshine搭建免费游戏串流服务器&#xff0c;让任何设备畅玩PC大作 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine 你是否曾梦想过在任何设备上都能玩到…...