音效素材网提供各类素材,打造精品素材网站!

站内导航 站长工具 投稿中心 手机访问

音效素材

.NET IoC模式依赖反转(DIP)、控制反转(Ioc)、依赖注入(DI)
日期:2021-09-07 22:47:17   来源:脚本之家

依赖倒置原则(DIP)

依赖倒置(Dependency Inversion Principle,缩写DIP)是面向对象六大基本原则之一。他是指一种特定的的解耦形式,使得高层次的模块不依赖低层次的模块的实现细节,依赖关系被颠倒(反转),从而使得低层次模块依赖于高层次模块的需求抽象.

该原则规定:

  • 高层次的模块不应该依赖低层次模块,二者都应该依赖其抽象接口.
  • 抽象接口不应该依赖于具体实现,而具体实现则应该依赖于抽象接口.

通过如下一个简单的示例,我们来看一下,我们通过一个简单地下单流程向我们的用户发送相关的短信或者邮件.

public SendingEmail
{
 public void Send(string message){
  //do something
 }
}

public Ordering
{
 SendingEmail _sendingEmail=null;
 public void Order(string message){
  //Order business operation
  if(_sendingEmail == null)
  {
   _sendingEmail=new SendingEmail();
  }
  _sendingEmail.Send(message);
 }
}

这样看我们的代码没问题,目前只要我们完成了订单操作那么,那么则会触发发送功能,但是他却违反了DIP,因为Ordering类依赖于SendingEmail类,而SendingEmail类不是抽象类,而是一个具体的类.那我们再来想一个如果这时候业务口的人过来向我们提出了一个新的需求,要求我们改为短信而不是Email,那么我们需要怎么改?

public class SendingSMS
{
 public void Send(string message){
  //do something
 }
}
public Ordering
{
 SendingEmail _sendingEmail=null;
 SendingSMS _sendingSMS=null;
 bool isSendingSMS=true;
 public void Order(string message){
  //Order business operation
  if(isSendingSMS){
   if(_sendingSMS == null)
   {
    _sendingSMS=new SendingSMS();
   }
   _sendingSMS.Send(message);
  }else{
   if(_sendingEmail == null)
   {
    _sendingEmail=new SendingEmail();
   }
   _sendingEmail.Send(message);
  }
  
 }
}

根据上述需求我们不得不创建更多的类,并且在Ordering类中声明他,最后我们还需要使用IF ELSE语句来决定使用SMS还是使用电子邮件.但是当我们有更多这种处理操作后,那么可能比现在还混乱,这就意味着我们必须在Ordering类中声明更多新的具体类的实例.

我们需要抽离出来一种方式,让高级模块去依赖于抽象,用它来代替我们实现类,该抽象将映射到实现类.

控制反转(IoC)

控制反转(Inversion of Control,缩写为IOC)是面向对象中的设计原则,他可以帮助我们使高层模块依赖于抽象,而不是底层模块的具体实现.换句话说,他有助于实现(依赖倒置原则——DIP).

public interface ICustomerCommunication
{
 void Send(string message);
}
然后我们修改SendingEmail和SendingSMS类以从ICustomerCommunication接口继承.

public class SendingEmail:ICustomerCommunication
{
 public void Send(string message){
  //do something
 }
}

public class SendingSMS:ICustomerCommunication
{
 public void Send(string message){
  //do something
 }
}

我们再来修改一下Ordering类以使用该抽象接口

public Ordering
{
 ICustomerCommunication _customerComm=null;
 bool isSendingSMS=true;
 public void Order(string message){
  //Order business operation
  if(isSendingSMS){
   if(_customerComm == null)
   {
    _customerComm=new SendingSMS();
   }
   _customerComm.Send(message);
  }else{
   if(_customerComm == null)
   {
    _customerComm=new SendingEmail();
   }
   _customerComm.Send(message);
  }
  
 }
}

通过如上修改我们做的控制反转更符合DIP.现在我们的高级模块只需要依赖于抽象,而不用去依赖实现.

依赖注入(DI)

依赖注入(Depeondency Injection,缩写为DI)是实现控制反转的一种方式.常用的依赖注入方法有3种:

  • 构造函数注入
  • 方法注入
  • 属性注入

虽然说通过上面代码我们实现了IoC,并且Ordering类依赖于ICustomerCommunication抽象,但我们仍然在Ordering类中使用了实现类,这使用我们无法在类于类之间完全解耦.

 if(isSendingSMS){
 if(_customerComm == null)
 {
  _customerComm=new SendingSMS();
 }
  _customerComm.Send(message);
 }else{
  if(_customerComm == null)
  {
   _customerComm=new SendingEmail();
  }
  _customerComm.Send(message);
 }

那我们再来说说DI,DI主要帮助我们将实现注入到抽象的类(ICustomerCommunication接口)中.DI的主要减少类之间的耦合,并且将抽象和具体实现的绑定移除依赖类.

构造函数注入

通过构造函数注入我们将实现类的对象传递给依赖类的构造函数,并将其分配给这个接口.

public class Ordering
{
 ICustomerCommunication _customerComm=null;
 public Ordering(ICustomerCommunication customerComm){
  _customerComm=customerComm;
 }
 public void Order(string message){
  _customerComm.Send(message);
 }
}

在上面的代码中,构造函数将采用实现类对象绑定到接口中.如果我们将SendingSMS的实现传递给这个类,我们要做的就是声明一个SendingSMS类的实例,然后将其传递给Ordering的构造函数,如下所示:

方法注入

通过使用构造函数注入,我们将不得不在Ordering类的生存期内使用实现类的实例SendingSMS或SendingEmail类.现在如果要在每次调用该方法时传递实现类的实例,则必须使用方法注入.

public class Ordering
{
 public void Order(ICustomerCommunication customerComm,string message){
  _customerComm=customerComm;
  _customerComm.Send(message);
 }
}

调用方式如下所示

SendingSMS sendingSMS=new SendingSMS();
Ordering ordering=new Ordering(sendingSMS);
ordering.Order(sendingSMS,"msg");

属性注入

通过如上描述我们知道了构造函数注入方法在整个生命周期中使用依赖类,而方法注入是将我们的注入直接去限于该方法中,然后我们再去了解一下属性注入

public class Ordering
{
 public ICustomerCommunication customerComm {get;set;}
 public void Order(string message){
  _customerComm.Send(message);
 }
}

调用方式如下所示

SendingSMS sendingSMS=new SendingSMS();
Ordering ordering=new Ordering(sendingSMS);
ordering.customerComm=sendingSMS;
ordering.Order("msg");

其实构造函数注入是实现DI最常用的方法.如果需要在每个方法调用上传递不同的依赖关系,则可以使用方法注入属性注入的使用还是比较少的.

Reference

https://zh.wikipedia.org/wiki/控制反转

https://zh.wikipedia.org/zh-hans/依赖反转原则

到此这篇关于.NET IoC模式依赖反转(DIP)、控制反转(Ioc)、依赖注入(DI)的文章就介绍到这了,更多相关.NET IoC模式依赖反转、控制反转、依赖注入内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

    您感兴趣的教程

    在docker中安装mysql详解

    本篇文章主要介绍了在docker中安装mysql详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编...

    详解 安装 docker mysql

    win10中文输入法仅在桌面显示怎么办?

    win10中文输入法仅在桌面显示怎么办?

    win10系统使用搜狗,QQ输入法只有在显示桌面的时候才出来,在使用其他程序输入框里面却只能输入字母数字,win10中...

    win10 中文输入法

    一分钟掌握linux系统目录结构

    这篇文章主要介绍了linux系统目录结构,通过结构图和多张表格了解linux系统目录结构,感兴趣的小伙伴们可以参考一...

    结构 目录 系统 linux

    PHP程序员玩转Linux系列 Linux和Windows安装

    这篇文章主要为大家详细介绍了PHP程序员玩转Linux系列文章,Linux和Windows安装nginx教程,具有一定的参考价值,感兴趣...

    玩转 程序员 安装 系列 PHP

    win10怎么安装杜比音效Doby V4.1 win10安装杜

    第四代杜比®家庭影院®技术包含了一整套协同工作的技术,让PC 发出清晰的环绕声同时第四代杜比家庭影院技术...

    win10杜比音效

    纯CSS实现iOS风格打开关闭选择框功能

    这篇文章主要介绍了纯CSS实现iOS风格打开关闭选择框,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作...

    css ios c

    Win7如何给C盘扩容 Win7系统电脑C盘扩容的办法

    Win7如何给C盘扩容 Win7系统电脑C盘扩容的

    Win7给电脑C盘扩容的办法大家知道吗?当系统分区C盘空间不足时,就需要给它扩容了,如果不管,C盘没有足够的空间...

    Win7 C盘 扩容

    百度推广竞品词的投放策略

    SEM是基于关键词搜索的营销活动。作为推广人员,我们所做的工作,就是打理成千上万的关键词,关注它们的质量度...

    百度推广 竞品词

    Visual Studio Code(vscode) git的使用教程

    这篇文章主要介绍了详解Visual Studio Code(vscode) git的使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...

    教程 Studio Visual Code git

    七牛云储存创始人分享七牛的创立故事与

    这篇文章主要介绍了七牛云储存创始人分享七牛的创立故事与对Go语言的应用,七牛选用Go语言这门新兴的编程语言进行...

    七牛 Go语言

    Win10预览版Mobile 10547即将发布 9月19日上午

    微软副总裁Gabriel Aul的Twitter透露了 Win10 Mobile预览版10536即将发布,他表示该版本已进入内部慢速版阶段,发布时间目...

    Win10 预览版

    HTML标签meta总结,HTML5 head meta 属性整理

    移动前端开发中添加一些webkit专属的HTML5头部标签,帮助浏览器更好解析HTML代码,更好地将移动web前端页面表现出来...

    移动端html5模拟长按事件的实现方法

    这篇文章主要介绍了移动端html5模拟长按事件的实现方法的相关资料,小编觉得挺不错的,现在分享给大家,也给大家...

    移动端 html5 长按

    HTML常用meta大全(推荐)

    这篇文章主要介绍了HTML常用meta大全(推荐),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参...

    cdr怎么把图片转换成位图? cdr图片转换为位图的教程

    cdr怎么把图片转换成位图? cdr图片转换为

    cdr怎么把图片转换成位图?cdr中插入的图片想要转换成位图,该怎么转换呢?下面我们就来看看cdr图片转换为位图的...

    cdr 图片 位图

    win10系统怎么录屏?win10系统自带录屏详细教程

    win10系统怎么录屏?win10系统自带录屏详细

    当我们是使用win10系统的时候,想要录制电脑上的画面,这时候有人会想到下个第三方软件,其实可以用电脑上的自带...

    win10 系统自带录屏 详细教程

    + 更多教程 +
    ASP编程JSP编程PHP编程.NET编程python编程