项目开发-依赖倒置、里式替换、接口隔离的应用深入理解

news2025/1/6 10:58:31

文章目录

  • 前言
  • 依赖倒置
    • 定义
    • 不符合依赖倒置原则是什么样子
    • 😄完善
  • 里式替换
    • 定义
    • 具体应用
  • 接口隔离
    • 定义
    • 具体应用

前言

最近在做.net项目和学习这个设计模式中的依赖倒置和工厂方法,这个过程当中发现在开发这个.net项目中有很多不合理的地方,就是我们使用了接口,但是在前端开发的时候还是使用的new的方式去给接口实例化,这还是违背了依赖倒置的原则。因为项目中并没有使用spring这些相关的框架,只是一个简单的三层模式UBD,之前在java项目中因为直接使用了spring的框架而忽略了在这个问题。
这里声明一下本次的代码示例均为Java语言。.net实现思路和这个一模一样。

依赖倒置

定义

依赖倒置原则(Dependency Inversion Principle)是面向对象设计中的一个原则,它是SOLID原则中的一部分,由罗伯特·C·马丁(Robert C. Martin)提出。该原则强调了高层模块不应该依赖于低层模块的具体实现细节,而应该依赖于抽象接口。具体来说,依赖倒置原则有以下几个核心概念:

  1. 模块间的依赖关系应该通过抽象发生,而不是具体实现发生。这意味着高层模块和低层模块都应该依赖于抽象接口或抽象类,而不是具体的实现类。

  2. 抽象不应该依赖于具体实现。抽象接口应该定义在高层模块中,并且不应该受到具体实现类的影响。这样可以保持高层模块的稳定性和独立性。

  3. 具体实现应该依赖于抽象。具体实现类应该依赖于抽象接口或抽象类,通过实现抽象定义的方法来完成具体的功能。

通过遵循依赖倒置原则,可以提高系统的可维护性、扩展性和灵活性。它可以降低模块间的耦合度,使得系统更容易进行修改和测试。另外,依赖倒置原则也促进了面向接口编程(Interface-Oriented Programming)的实践,强调了定义良好的抽象接口和合理的接口设计。

需要注意的是,依赖倒置原则并不是要求完全避免依赖关系,而是通过合理的抽象和接口设计来管理和控制依赖关系,以提高系统的灵活性和可维护性。

不符合依赖倒置原则是什么样子


import com.example.onlystudent.DIPDemo.Dao.ItemDao;
import com.example.onlystudent.DIPDemo.Dao.ItemDao4MysqlImpl;

//B层实现类。
public class ItemManagerImpl {
    //作为B层,这里是直接依赖的D层的代码,可以看到使用的是D层的接口。
    // 但是还是在给接口实例化的时候使用到了具体的实现来,并且在这个B层的import中出现了实现类的相关信息。
    ItemDao itemDao=new ItemDao4MysqlImpl();
}

package com.example.onlystudent.DIPDemo.Dao;

//D层接口
public interface ItemDao {
	//仅做demo展示,并为声明任何方法 
}
package com.example.onlystudent.DIPDemo.Dao;

//D层接口的实现类,这里是一个MySQL语法的实现类
public class ItemDao4MysqlImpl implements ItemDao {
    	//仅做demo展示,并为声明任何方法 
}
package com.example.onlystudent.DIPDemo.Dao;
//D层接口的实现类,这里是一个Oracle语法的实现类
public class ItemDao4OracleImpl implements ItemDao{
	//仅做demo展示,并为声明任何方法 
}

在这套代码中虽然也声明了接口,也有实现类,但是在具体使用过程中并没有遵循依赖倒置原则。体现在上述的ItemManagerImpl类中,因为按照依赖倒置原则在ItemManagerImpl类中只能出现D层的ItemDao的信息。它应该只知道ItemDao,如果现在需要更换数据库,那么就需要更改ItemManagerImpl中的代码,将new ItemDao4MysqlImpl()修改为new ItemDao4OracleImpl(),但是这并不符合开闭原则,所以这里使用的这个依赖倒置并不完善,或者说是仅仅有了一个形式上的依赖倒置,但是本质上并没有改变ItemManagerImpl有依赖于具体实现类。

😄完善

如何修改上面的代码,做到符合依赖倒置的原则呢?这就需要用到反射这个强大的功能,首先要添加一个配置文件。
在配置文件中加上需要反射的类路径,在这个demo中需要反射的类是mysql实现类。
在这里插入图片描述
添加完配置文件中的信息后,需要有一个读取配置文件的类,来获取配置文件中的类路径信息

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
/**
 * @Description: 读取配置文件
 */
public class PropertiesReader {
    public static String getValue(String key) {
        Properties properties = new Properties();
        FileInputStream fis = null;
        String value="";
        try {
            fis = new FileInputStream("application.properties");
            properties.load(fis);
            // 读取配置项
            value= properties.getProperty(key);
            return value;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {

            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return value;
    }
}

有了以上的这些准备后,现在开始修改ItemManagerImpl这个类中的依赖问题

new这个操作删除,修改为通过反射来获取对象。
通过使用反射加配置文件在构造函数中将itemDao给实例化出对象来。这样就符合了依赖倒置,这个时候在看ItemManagerImpl类中它的依赖中就只有ItemDao这个接口了。
在这里插入图片描述

后期项目中如果需要更换数据库,那这里去操作出数据库的类,就可以在配置文件中进行更换,只需将类路径更换即可。以上这些操作只是为了简单的描述出来,依赖倒置具体的实现和应用。实际开发过程中要考虑的还是很多的,比如对象怎么管理啊这些工作。

里式替换

定义

里氏替换原则的内容可以描述为: “派生类(子类)对象可以在程式中代替其基类(超类)对象。

具体应用

在上述的代码中其实就是基于里式替换实现的,虽然在定义中说是基类和派生类,但是接口同样适用里式替换的原则,根据里式替换原则,如果一个类通过实现一个接口来表达其行为,那么在使用接口时,任何实现该接口的类都应该能够替换该接口,而不会破坏程序的正确性。
具体体现在ItemDao itemDao=new ItemDao4MysqlImpl();虽然后面修改为了反射获取,通过类型转换为了ItemDao

itemDao=(ItemDao)Class.forName(PropertiesReader.getValue("itemDao")).newInstance();

但是这依然符合。

接口隔离

定义

接口隔离原则的核心思想是将庞大而臃肿的接口拆分为更小、更具体的接口,使得每个接口只包含客户端所需的方法。这样可以降低类和模块之间的耦合度,减少对不相关方法的依赖,提高代码的灵活性、可维护性和可复用性。
以下是接口隔离原则的几个要点:

  1. 接口应该精简而专注于特定的功能领域。不应该设计臃肿的接口,包含大量不相关的方法。

  2. 客户端不应该强制依赖于它不需要的接口。一个类或模块只应该依赖于它需要使用的接口,而不是依赖于多余的接口。

  3. 接口隔离原则鼓励根据不同的客户端需求定义多个小接口,而不是一个大而全的接口。这样可以提供更高的灵活性和可扩展性。

  4. 接口设计应该符合单一职责原则,即一个接口只负责定义一个单一的功能或角色。

具体应用

接口隔离原则在我们上述的依赖倒置这里其实就已经体现了,访问数据库的操作行为抽象为一个接口,这个接口包含了数据库操作的所有行为,而作为B层的ItemManagerImpl来说,它只依赖于接口,而具体的实现类单独写,如果后期需要添加信息的数据库,直接添加一个实现类即可,搭配着依赖倒置的原则和里式替换,通过反射去创建对象。程序的灵活性就大大提高了。
在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/582828.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(转载)基于粒子群算法的多目标搜索算法(matlab实现)

1 理论基础 在实际工程优化问题中,多数问题是多目标优化问题。相对于单目标优化问题,多目标优化问题的显著特点是优化各个目标使其同时达到综合的最优值。然而,由于多目标优化问题的各个目标之间往往是相互冲突的,在满足其中一个…

KD7742交直流耐压绝缘分析仪

一、产品简介 KD7742交直流耐压绝缘分析仪具有交/直流耐压、绝缘电阻等项目的测试分析功能,能显示电压、电流和电阻的波形图以及趋势图,以便更直观的监测分析绝缘性能和绝缘崩溃时的各项指标,适用于高要求的测试分析场合。 产品具有测试参数范…

vue实现二维码识别功能 读取二维码内容

我们可以访问 https://www.wwei.cn/?frombdtp 在输入框中输入文本 然后 点击生成二维码 他就会给我生成一个对应信息的二维码图片 我们可以复制到本地 打开vue项目 先引入依赖 npm install canvas jsqr然后组件编写代码如下 <template><div><input type&qu…

首届中国元宇宙应用场景大赛成果发布暨河畔元宇宙论坛圆满落幕

5月26日下午&#xff0c;首届中国元宇宙应用场景大赛成果发布暨河畔元宇宙论坛在北京城市副中心圆满落幕。活动在通州区委、区政府指导下&#xff0c;由北京大数据协会元宇宙专业委员会主办&#xff0c;中国质量认证中心、绿色智能新经济产业联盟、中关村元宇宙产业发展联盟协办…

【大数据处理与可视化】八、文本数据分析

【大数据处理与可视化】八、文本数据分析 实验目的实验内容实验步骤一、案例——商品评价分析1、读取数据&#xff0c;并转换成DataFrame对象进行展示。2、从输出的结果看&#xff0c;多条评价信息是没用且重复的&#xff0c;所以&#xff0c;要用pandas中的drop_duplicates()方…

Java笔记039-多用户即时通信系统

目录 多用户即时通信系统 项目介绍 项目演示 项目结构 涉及到Java的技术 项目开发流程 需求分析 界面设计 功能实现-用户登录 1、功能说明 2、思路分析程序框架图 3、代码实现 功能实现-拉去在线用户列表 1、功能说明 2、思路分析程序框架图 3、代码实现 功能…

什么是LIS系统?LIS系统的优势有哪些?

一、LIS系统 LIS系统(Laboratory Information System) 即 实验室&#xff08;检验科&#xff09;信息系统&#xff0c;它是医院信息管理的重要组成部分之一。 LIS系统是实验室信息管理系统&#xff0c;是医院信息管理的重要组成部分。它采用智能辅助功能&#xff0c;自动接收检…

【分布式文件存储】MinIO部署及实现文件上传下载

目录 概述 MinIO集群部署 准备docker-compose.yml 测试启动 MinIO用户管理 Buckets管理 创建Buckets MinIO客户端 引入依赖 文件上传下载Demo 调用API碰到的问题 概述 MinIO | 高性能, Kubernetes 原生对象存储 MinIO是全球领先的对象存储先锋&#xff0c;目前在全世…

TCP协议的RST标志

下文中的内容多数来自【参考】中的文章&#xff0c;这边进行一个整理和总结&#xff0c;后续会慢慢增加出现各个 RST 包的测试代码&#xff0c;便于理解。 TCP的 “断开连接” 标志 RST 标志 Reset&#xff0c;复位标志&#xff0c;用于非正常地关闭连接。它是 TCP 协议首部里…

企业产品操作手册,真的很有必要吗?

产品操作手册是一种对于产品使用者而言非常重要的工具。它是一份向用户介绍产品使用方法和功能的文档&#xff0c;可以提供关于产品的详细信息&#xff0c;解答用户的疑问&#xff0c;并帮助用户快速上手使用产品。 产品操作手册的必要性&#xff1a; 一、提高用户使用体验 …

Matlab论文插图绘制模板第95期—双向柱状图

在之前的文章中&#xff0c;分享了很多Matlab柱状图的绘制模板&#xff1a; 进一步&#xff0c;再来看一种特殊的柱状图&#xff1a;双向柱状图。 先来看一下成品效果&#xff1a; 特别提示&#xff1a;本期内容『数据代码』已上传资源群中&#xff0c;加群的朋友请自行下载。…

抖音seo源码如何开发部署?

前言&#xff1a;抖音seo源码&#xff0c;抖音矩阵系统源码搭建&#xff0c;抖音矩阵同步分发。抖音seo源码部署是需要对接到这些正规接口再来做开发的&#xff0c;目前账号矩阵程序开发的功能&#xff0c;围绕一键管理多个账号&#xff0c;做到定时投放&#xff0c;关键词自动…

腾讯云服务器常用端口号大全以及端口开启方法

腾讯云服务器常用端口号如80、21、22、8080等端口&#xff0c;出于安全考虑一些常用端口默认是关闭的&#xff0c;腾讯云服务器端口如何打开呢&#xff1f;云服务器CVM在安全组中开启端口&#xff0c;轻量应用服务器在防火墙中可以打开端口&#xff0c;腾讯云百科来详细说下腾讯…

解析云盘存储的优缺点:安全靠谱还是存在风险?

云盘是一种基于云计算技术的在线存储服务&#xff0c;用户可以通过互联网将文件上传到云端&#xff0c;并可以随时随地通过网络访问这些文件。 相较于传统的本地存储&#xff0c;云盘具有以下优势&#xff1a; 1.数据安全性更高&#xff1a;云盘使用专业的云计算技术和安全措施…

vue 截取字符串的方法

vue中的字符串方法&#xff0c;我目前使用最多的是下面两种方法&#xff0c;因为 vue的字符串方法支持断言操作。 1、 vue中截取字符串的方法如下&#xff1a; 2、 vue中截取字符串的方法&#xff0c;这个方法也是需要依赖于 vue库提供的支持。 3、 vue中截取字符串的方法&…

腾讯云服务器CVM和轻量应用服务器区别

关于腾讯云轻量应用服务器和云服务器CVM的区别&#xff0c;之前腾讯云百科写过一篇文章来对比&#xff0c;如今2023阿腾云又更新了一篇新的区别对比文章&#xff0c;比之前的要更加详细&#xff0c;包括轻量服务器的使用限制、CPU型号、公网限制月流量、内网连通性、硬盘存储等…

f1c200s---编译uboot

目录 前言安装必要工具安装交叉编译链工具 下载Uboot切换分支查看配置文件 配置Uboot修改Makefile配置文件 编译uboot出现/bin/sh: 1: python: not found错误出现multiple definition of yylloc错误出现FATAL ERROR: Unable to parse input tree错误出现/usr/bin/env: python2:…

微服务架构综合实战 一文让你了解什么是微服务 使用PHP 搭建微服务框架 最全微服务架构讲解以及演示

本文将带你从基础的微服务架构设计、网络协议、注册中心、配置中心、网关层面 渐进式讲解其微服务。 一、微服务架构设计方案 架构演进 在将微服务之前 我们看看目前的架构 单体架构 按照模块划分&#xff0c;公用一个数据库 垂直拆分架构 按业务功能划分单独的子系统&…

为什么pnpm比npm、yarn使用更好

performant npm &#xff0c;意味高性能的 npm。pnpm由 npm/yarn 衍生而来&#xff0c;解决了 npm/yarn 内部潜在的bug&#xff0c;极大的优化了性能&#xff0c;扩展了使用场景。被誉为"最先进的包管理工具"。 我们按照包管理工具的发展历史开始讲起&#xff1a; n…

切片工具tippecanoe的全网最详细的解释

1.下载和安装 tippecanoe工具是mapbox官方提供的一个服务端切片工具,因此它是运行在服务器上的,它比较友好的支持mac和linux机器。对于windows来讲,就比较麻烦了。 首先对于mac系统,你只需配置好自己的homebrew,保证homebrew能够正常下载东西。 然后只需要一个命令: …