C# 实例解释面向对象编程中的依赖反转原则
在面向对象编程中,SOLID 是五个设计原则的首字母缩写,旨在使软件设计更易于理解、灵活和可维护。这些原则是由美国软件工程师和讲师罗伯特·C·马丁(Robert Cecil Martin)提出的许多原则的子集,在他2000年的论文《设计原则与设计模式》中首次提出。
SOLID 原则包含:
- S:单一功能原则(single-responsibility principle)
- O:开闭原则(open-closed principle)
- L:里氏替换原则(Liskov substitution principle)
- I:接口隔离原则(Interface segregation principle)
- D:依赖反转原则(Dependency inversion principle)
本文我们来介绍依赖反转原则。
依赖反转原则
在面向对象编程领域中,依赖反转原则(Dependency inversion principle,DIP)是指一种特定的解耦形式,使得高层次的模块不依赖于低层次模块的实现细节,依赖关系被颠倒(反转),从而使低层次模块依赖于高层次模块的需求抽象。(传统的依赖关系创建在高层次上,而具体的策略设置则应用在低层次的模块上)
(图1 中,高层 对象A 依赖于低层 对象B 的实现;图2 中,把高层 对象A 对低层对象的需求抽象为一个 接口A,低层 对象B 实现了 接口A,这就是依赖反转。)
依赖反转原则约定:
- 高层次的模块不应该依赖于低层次的模块,两者都应该依赖于抽象接口。
- 抽象接口不应该依赖于具体实现。而具体实现则应该依赖于抽象接口。
该原则颠倒了一部分人对于面向对象设计的认识方式(如高层次和低层次对象都应该依赖于相同的抽象接口)。
依赖注入是该原则的一种实现方式。
C# 示例
先定义一个商品信息类:
public class ProductInfo
{
public int ID { get; set; }
public string ProductName { get; set; }
public string ProductSpec { get; set; }
public int Stock { get; set; }
}
糟糕的示范
新建一个数据访问类 ProductDataAccess 和业务逻辑类 ProductBusinessLogic:
public class ProductDataAccess
{
public ProductInfo GetDetail(int id)
{
ProductInfo product = new()
{
ID = id,
ProductName = "白糖",
ProductSpec = "500g",
Stock = 100
};
return product;
}
}
public class ProductBusinessLogic
{
private readonly ProductDataAccess _productDataAccess;
public ProductBusinessLogic()
{
_productDataAccess = new ProductDataAccess();
}
public ProductInfo GetProductDetails(int id)
{
return _productDataAccess.GetDetail(id);
}
}
在上面的代码中,高层次的类 ProductBusinessLogic 直接依赖于低层次的类 ProductDataAccess,这明显违反了 依赖反转原则。
正确的示范
根据 依赖反转原则 的要求,我们把高层对象 ProductBusinessLogic 对低层对象的需求抽象为一个接口 IProductDataAccess:
public interface IProductDataAccess
{
ProductInfo GetDetail(int id);
}
在低层对象 ProductDataAccess 中实现接口 IProductDataAccess,然后在高层对象 ProductBusinessLogic 中引用(注入)接口 IProductDataAccess:
public class ProductDataAccess : IProductDataAccess
{
public ProductInfo GetDetail(int id)
{
ProductInfo product = new()
{
ID = id,
ProductName = "白糖",
ProductSpec = "500g",
Stock = 100
};
return product;
}
}
public class ProductBusinessLogic
{
private readonly IProductDataAccess _productDataAccess;
public ProductBusinessLogic(IProductDataAccess productDataAccess)
{
_productDataAccess = productDataAccess;
}
public ProductInfo GetProductDetails(int id)
{
return _productDataAccess.GetDetail(id);
}
}
这样,这些类的设计便遵守了依赖反转原则。
其实,ASP.NET Core 中服务的依赖注入正是遵循了依赖反转原则。
总结
本文我介绍了 SOLID 原则中的依赖反转原则(Dependency inversion principle),并通过 C# 代码示例简明地诠释了它的含意和实现,希望对您有所帮助。
作者 : 技术译民
出品 : 技术译站
参考文档:
- https://en.wikipedia.org/wiki/SOLID
- https://www.c-sharpcorner.com/blogs/dependency-inversion-principle-in-c-sharp
- https://flylib.com/books/en/4.444.1.71/1/
C# 实例解释面向对象编程中的依赖反转原则的更多相关文章
- C# 实例解释面向对象编程中的单一功能原则
在面向对象编程中,SOLID 是五个设计原则的首字母缩写,旨在使软件设计更易于理解.灵活和可维护.这些原则是由美国软件工程师和讲师罗伯特·C·马丁(Robert Cecil Martin)提出的许多原 ...
- C# 实例解释面向对象编程中的开闭原则
在面向对象编程中,SOLID 是五个设计原则的首字母缩写,旨在使软件设计更易于理解.灵活和可维护.这些原则是由美国软件工程师和讲师罗伯特·C·马丁(Robert Cecil Martin)提出的许多原 ...
- C# 实例解释面向对象编程中的里氏替换原则
在面向对象编程中,SOLID 是五个设计原则的首字母缩写,旨在使软件设计更易于理解.灵活和可维护.这些原则是由美国软件工程师和讲师罗伯特·C·马丁(Robert Cecil Martin)提出的许多原 ...
- C# 实例解释面向对象编程中的接口隔离原则
在面向对象编程中,SOLID 是五个设计原则的首字母缩写,旨在使软件设计更易于理解.灵活和可维护.这些原则是由美国软件工程师和讲师罗伯特·C·马丁(Robert Cecil Martin)提出的许多原 ...
- C#中面向对象编程中的函数式编程详解
介绍 使用函数式编程来丰富面向对象编程的想法是陈旧的.将函数编程功能添加到面向对象的语言中会带来面向对象编程设计的好处. 一些旧的和不太老的语言,具有函数式编程和面向对象的编程: 例如,Smallta ...
- Dart编程实例 - Dart 面向对象编程
Dart编程实例 - Dart 面向对象编程 class TestClass { void disp() { print("Hello World"); } } void main ...
- 依赖反转原则DIP 与 asp.net core 项目结构
DIP 依赖反转原则 Dependency Inversion Principle 的定义如下: 高级别的模块不应该依赖于低级别的模块, 他们都应该依赖于抽象. 假设Controller依赖于Repo ...
- 依赖反转原则DIP 与使用了Repository模式的asp.net core项目结构
DIP 依赖反转原则 Dependency Inversion Principle 的定义如下: 高级别的模块不应该依赖于低级别的模块, 他们都应该依赖于抽象. 假设Controller依赖于Repo ...
- Python3学习之路~6.2 实例演示面向对象编程的好处
首先建一个dog类,实例化为3个dog对象,并让它们都叫. class Dog: def bulk(self): print("xiaohuang:wang wang wang !" ...
随机推荐
- 实战 target 选择器,解放生产力!
大家好,我是半夏,一个刚刚开始写文的沙雕程序员.如果喜欢我的文章,可以关注 点赞 加我微信:frontendpicker,一起学习交流前端,成为更优秀的工程师-关注公众号:搞前端的半夏,了解更多前端知 ...
- Java学习笔记-基础语法Ⅸ-文件
File File是文件和路径名的抽象表示,File封装的并不是一个真正存在的文件,是一个路径名,可以存在也可以不存在 常用方法: 创建文件:createNewFile() 创建目录:mkdir() ...
- Volatile的学习
首先先介绍三个性质 可见性 可见性代表主内存中变量更新,线程中可以及时获得最新的值. 下面例子证明了线程中可见性的问题 由于发现多次执行都要到主内存中取变量,所以会将变量缓存到线程的工作内存,这样当其 ...
- 20212115朱时鸿实验一《python程序设计》实验报告
------------恢复内容开始------------ #学号20212115 <python程序设计>实验一报告 课程: <python程序设计> 班级:2121 姓名 ...
- [2-SAT]编码
题意:给n个01字符串,每个最多包含1个'?',能否构造出满足两两不存在一个是另一个前缀的方案. 思路: 2-SAT+trie树优化建图 把每个字符串拆成i,i+n,如果不存在'?',就硬搞出两种情况 ...
- ERP采购收货在标准成本和移动平均价下的差别
欢迎关注微信公众号:iERPer (ERP咨询顾问之家) ERP系统在处理主要的采购流程有: 下采购合同->下采购订单->收货->发票校验->付款(财务) 其中 收货和发票校验 ...
- 数据库常用DDL语句
一.创建表 CREATE TABLE TABLE_NAME( #create table 表名 ID INT(4) PRIMARY KEY, #字段名 数据类型 完整性约束条件 NAME VARCHA ...
- React项目中使用less/scss&全局样式/变量
使用create-react-app脚手架搭建初始化项目 > npm install -g create-react-app > npx create-react-app my-app c ...
- JZOJ 5409 Fantasy & NOI 2010 超级钢琴 题解
其实早在 2020-12-26 的比赛我们就做过 5409. Fantasy 这可是紫题啊 题目大意 给你一个序列,求长度在 \([L,R]\) 区间内的 \(k\) 个连续子序列的最大和 题解 如此 ...
- vue根据后端菜单自动生成路由(动态路由)
vue根据后端菜单自动生成路由(动态路由) router.js import Vue from 'vue' import Router from 'vue-router' import store f ...