什么是依赖注入


99%开发者都在项目中使用过依赖注入,但是没有意识到,那么什么是 依赖注入呢?

1. 举个例子

以手机为例,我们知道,手机需要插入SIM卡才可以正常的拨打电话,也就是说,手机的通话功能依赖于SIM卡。

1.1 不使用依赖注入的代码实现

这里新建SimCard类和MobilePhone类,如下:

class SimCard{
    private val TAG = "SimCard"
    fun dialNumber()
    {
    	log.d(TAG,"拨打电话")
    }
}
class MobilePhone{
   fun diaNumber()
   {
      val simCard = SimCard()
      simCard.dialNumber()
   }
}

使用MobilePhone类中的拨打电话方法,如下:

     val mobilePhone = MobilePhone()
     mobile.dialNumber()

1.1.1 解释说明

通过前面的代码可以知道,当调用MobilePhone的dialNumber方法时,首先会在MobilePhone类的dialNumber方法中创建SimCard对象,然后会调用SimCard对象的dialNumber方法。
在这种实现方式中,MobilePhone 类虽然依赖SimCard类,使用依赖类是由MobilePhone类的方法自己创建的。

1.2 使用依赖注入的实现

很简单,SimCard类保持不变,修改MobilePhone的dialNumber方法,传入一个SimCard对象。

class SimCard{
    private val TAG = "SimCard"
    fun dialNumber()
    {
    	log.d(TAG,"拨打电话")
    }
}
class MobilePhone{
   fun dialNumber(simCard: SimCard)
      simCard.dialNumber()
   }
}

使用MobilePhone类中的拨打电话方法,如下:

     val mobilePhone = MobilePhone()
     val simCard = SimCard()
     mobilePhone.dialNumber(simCard)

1.2.1 解释说明

上述代码中,我们创建论mobilePhone对象和simCard对象,并将simCard对象传递给给mobilePhone对象的dialNumber方法,这种实现方式就是依赖注入。

2. 依赖注入的定义

一个类中使用依赖类,这个依赖类不是由使用它的类创建的,而是通过构造函数或者属性方法传入的。

3. 使用依赖注入由什么好处呢?

在不使用依赖注入的实现中,MobilePhone类不仅要负责自身类的功能,还要负责创建SimCard类的对象。使用依赖注入不仅仅可以提高代码的可扩展性,还可以分离依赖项目。

扩展性体现在哪里呢?
我们假设为不同的运行商的SIM卡创建不同的类,这些类都以SimCard为基类。
假设有 中国移动,中国联通,中国电信 三种SIM卡。

class SimCard{
    private val TAG = "SimCard"
    fun dialNumber()
    {
    	log.d(TAG,"拨打电话")
    }
}
class ChinaMobile:SimCard
{
    @override fun dialNumber()
    {
    	log.d(TAG,"中国移动拨打电话")
    }
}
class ChinaUnicom:SimCard
{
    @override fun dialNumber()
    {
    	log.d(TAG,"中国联通拨打电话")
    }
}
class ChinaTelecom:SimCard
{
    @override fun dialNumber()
    {
    	log.d(TAG,"中国电信拨打电话")
    }
}

假设现在MobilePhone 支持中国移动的卡。

class MobilePhone{
   fun diaNumber()
   {
      val simCard = ChinaMobile()
      simCard.dialNumber()
   }
}

现在要支持中国联通和中国电信的SIM卡。
不使用依赖注入的话,需要修改MobilePhone的代码,在MobilePhone 的dialNumber方法为不同的卡创建不同实例。

class MobilePhone{
   fun dialNumber(cardType:String)
   {
      if(cardType == "ChinaMobile")
      {
	      val simCard = ChinaMobile()
	      simCard.dialNumber()
      }
      else if(cardType == "ChinaUnicom")
      {
	      val simCard = ChinaUnicom()
	      simCard.dialNumber()
      }
      else if(cardType == "ChinaTelecom")
      {
	      val simCard = ChinaTelecom()
	      simCard.dialNumber()
      }
   }
}
//使用时
val mobiePhone = MobilePhone()
mobiePhone.dialNumber("ChinaMobile")
mobiePhone.dialNumber("ChinaUnicom")
mobiePhone.dialNumber("ChinaTelecom")

由于dialNumber本身并不是mobilePhone来实现的,但是为了增加对不同SIM卡的支持需要修改mobilePhone的代码。
如果使用依赖注入的话,我们就不必修改MobilePhone中的dialNumber方法了,直接传入不同运行商的SIM卡对象即可。

class MobilePhone{
   fun dialNumber(simCard: SimCard)
   {
      val simCard = ChinaTelecom()
      simCard.dialNumber()

   }
}
//使用时
val mobiePhone = MobilePhone()
val chinaMobile = ChinaMobile()
val chinaUnicom= ChinaUnicom()
val chinaTelecom= ChinaTelecom()
mobiePhone.dialNumber(chinaMobile )
mobiePhone.dialNumber(chinaUnicom)
mobiePhone.dialNumber(chinaTelecom)

这样,MobilePhone类增加对新的SIM卡的支持,就不需要修改MobilePhone类的代码了,只需要给SimCard类增加新的子类即可。
不使用依赖注入的写法,违反了开闭原则,即:一个类,对扩展是开放的,对修改是封闭的。增加新功能,不应该修改现有的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李来群

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值