讲到底核心就是面向接口编程。
注入的目的是解耦,当然我们不可能做到完全的解耦,我们只是消减了耦合的强弱,又或者说你把对具体实现类的直接耦合降解为通过依赖接口的间接耦合。而解耦带来了以下的好处:
1. 方便写unit test。因为unit test是一次只关注一个或几个模块,极少全连在一起写测试。于是就要要替换一些做实际操作的模块,比如说写数据库。而如果你把new什么class写死在代码里,这就不太方便unit test来替换它。当然,这里也有别的技术可以mock,但ioc相对来说更简单方便的。
2. 日后升级或修改一个模块更容易。这也是常见的需求,比如说你现在的实现是写入本地文件,你将来可能要写入hdfs,那么只要这两种实现符合同一个接口,那么通过ioc,你将来的升级和替换就可以容易的做到零代码改动。或者你修改一个class的时候,只要不动它的接口,就不会需要改动其他模块。同样的,实现类似的目的你也可以使用其他的设计模式,不过IOC也是其中比较简单易用的一个。
有些朋友提出业务系统里没有也不需要这种可替换模块的设计,因为这会增加的系统的复杂性,我只能部分同意这个观点,现在很多系统的确有些over engineering,接口泛滥,滥用注入等等。所以我同意你说把系统里每一个类都琢磨成可替换的,那这是对ioc的滥用,但你要说写业务系统就轮不到考虑这种灵活性,那就是对系统设计的不负责任,系统的灵活性和可扩展性既不能过分考虑但也不能一点都不考虑,我们要具体案例具体分析,追寻一个平衡。
3. 可以减少依赖关系的复杂度。如果我们都是具体的class依赖其他具体的class,这就很容易形成一个依赖关系网,早晚要造成循环依赖。而如果我们是具体class对接口依赖,而接口又不依赖其他具体class,那么这个依赖关系就是个树或者是一个DAG,就不容易造成循环依赖。
使用ioc也不是没有坏处,比如说就让你的代码实现没有那么直观了,你一下子就看不出调用模块的具体实现是啥。但随着软件系统的复杂度提升,高耦合才是系统设计更关注的问题,这也是IOC等解耦技术会大行其道的原因。
我再补充说一下IOC的其他好处,多谢小石头在评论区的回复,IOC还有几个作用对软件系统的实现很有帮助。