首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >什么时候使用依赖注入模式不合适?

什么时候使用依赖注入模式不合适?
EN

Software Engineering用户
提问于 2012-02-20 09:57:19
回答 9查看 74.6K关注 0票数 163

自从学习(和热爱)自动化测试以来,我发现自己几乎在每个项目中都使用了依赖注入模式。在使用自动化测试时,使用这种模式总是合适的吗?有什么情况需要避免使用依赖注入吗?

EN

回答 9

Software Engineering用户

回答已采纳

发布于 2012-02-21 11:11:52

基本上,依赖注入对对象的性质做出了一些(通常但并非总是有效的)假设。如果这些都是错误的,DI可能不是最好的解决方案:

  • 首先,基本上,DI假设对象实现的紧密耦合总是不好的。这就是依赖倒置原则的本质:“依赖不应建立在具体的基础上,而只应建立在抽象上”。这将关闭依赖对象以根据对具体实现的更改进行更改;如果输出需要转到文件中,则依赖于ConsoleWriter的类将需要更改,但是如果类仅依赖于一个IWriter,则可以用FileWriter替换当前使用的ConsoleWriter,并且我们的依赖类将不知道两者的区别(Liskhov替换原则)。但是,设计绝不能对所有类型的更改关闭;如果IWriter接口本身的设计发生变化,为了添加要写入()的参数,必须在实现对象/方法及其用法(S)之上更改额外的代码对象( IWriter接口)。如果实际接口中的更改比对所述接口的实现的更改更有可能发生,则松散耦合(以及依赖松散耦合的DI-ing )可能会导致比它解决的更多的问题。
  • 第二,也是推论,DI假设依赖类从来不是创建依赖关系的好地方。这就是单一责任原则;如果您有创建依赖项并同时使用它的代码,那么依赖类可能必须更改两个原因(更改使用或实现),这违反了SRP。但是,为DI添加层间接性可能是一个不存在的问题的解决方案;如果将逻辑封装到依赖项中是合乎逻辑的,但该逻辑是依赖关系的唯一此类实现,那么编写依赖关系的松散耦合解决方案(注入、服务位置、工厂)要比仅仅使用new而忘记它要痛苦得多。
  • 最后,DI本质上集中了所有依赖项及其实现的知识。这增加了执行注入的程序集必须具有的引用数,而且在大多数情况下不会减少实际依赖类程序集所需的引用数。在某个地方,为了“连接点”并满足这种依赖关系,必须了解依赖关系、依赖接口和依赖关系实现。DI倾向于将所有这些知识放在一个非常高的级别上,要么放在IoC容器中,要么放在创建“主”对象的代码中,比如主窗体或控制器,这些对象必须水合物(或为依赖提供工厂方法)。这可以在应用程序的高级别上放置大量必要的紧密耦合的代码和大量的程序集引用,而应用程序只需要这些知识来“隐藏”实际的依赖类(从非常基本的角度来看,这些类是拥有这些知识的最佳地方;它是使用的地方)。它通常也不会从代码的较低处删除上述引用;依赖方仍然必须引用包含其依赖项的接口的库,该库位于以下三个位置之一:
    • 所有的程序集都是以应用为中心的“接口”程序集,
    • 在主实现(S)旁边的每个实现,消除了在依赖关系更改时不必重新编译受抚养人的优点,或者
    • 在高度内聚的程序集中,每个程序集中有一两个,这会使程序集数量增加,大大增加“完整构建”次数,并降低应用程序性能。

所有这些,再一次解决一个可能没有问题的地方。

票数 159
EN

Software Engineering用户

发布于 2012-02-20 16:39:56

在依赖注入框架之外,依赖注入(通过构造函数注入或setter注入)几乎是一个零和游戏:您减少了对象A与其依赖项B之间的耦合,但现在任何需要A实例的对象现在也必须构造对象B。

您已经稍微减少了A和B之间的耦合,但是减少了A的封装,增加了A和任何必须构造A实例的类之间的耦合,方法是将它们耦合到A的依赖项。

因此,依赖注入(没有框架)同样有害,因为它是有用的。

然而,额外的成本通常是合理的:如果客户端代码比对象本身更了解如何构造依赖项,那么依赖注入确实减少了耦合;例如,Scanner不知道如何获得或构造要解析输入的输入流,或者客户端代码希望解析输入的源,因此构造函数注入输入流是显而易见的解决方案。

为了能够使用模拟依赖项,测试是另一个理由。这应该意味着添加一个只用于测试的额外构造函数,该构造函数允许注入依赖关系:如果您将构造函数更改为总是要求注入依赖项,那么突然之间,您必须了解依赖项的依赖项,才能构造直接依赖关系,并且无法完成任何工作。

这可能很有帮助,但是您应该明确地问自己每个依赖项,测试的好处值得花费吗?我真的想在测试时模拟这种依赖吗?

当添加依赖注入框架,并且依赖关系的构造不是委托给客户端代码,而是委托给框架时,成本/效益分析就会发生很大的变化。

在依赖注入框架中,权衡有一点不同;注入依赖关系所失去的是,您能够轻松地知道您所依赖的实现,并将决定您所依赖的依赖项的责任转移到某些自动解决过程(例如,如果我们需要一个@ injecting‘’ed,必须有某种东西“提供Foo,其注入的依赖项是可用的)”,或者是一些高级配置文件,该文件规定了每个资源应该使用什么提供程序,或者是这两者的某个混合体(例如,对于依赖项可能会有一个自动解决过程,如果必要的话,可以使用配置文件)。

在构造函数注入中,我认为这样做的好处同样与这样做的成本非常相似:您不需要知道是谁提供了您所依赖的数据,如果有多个潜在的提供程序,您不需要知道首选的检入提供程序的顺序,确保每个需要对所有潜在提供者进行数据检查的位置,等等,因为所有这些都是由依赖注入平台在较高级别上处理的。

虽然我个人对DI框架没有太多的经验,但我的印象是,当查找您需要的数据或服务的正确提供者时,当您需要的数据或服务的正确提供者遇到麻烦时,当某些事情失败时,无法立即知道本地是什么代码提供了错误的数据,导致您的代码出现故障时,它们带来的好处大于成本。

在某些情况下,在DI框架出现时,已经采用了一些模糊依赖关系的模式(例如服务定位器)(也许也证明了它们的价值),而采用DI框架是因为它们提供了一些竞争优势,例如需要更少的样板代码,或者在需要确定实际使用的提供者时,更少地掩盖依赖关系的提供者。

票数 41
EN

Software Engineering用户

发布于 2012-02-20 14:09:02

  1. 如果要创建数据库实体,则应该有一些工厂类,然后将其插入到控制器中,
  2. 如果您需要创建像int或long这样的原始对象。此外,您应该创建“手动”大多数标准库对象,如日期、guids等。
  3. 如果您想注入配置字符串,最好是注入一些配置对象(通常,建议将简单类型封装到有意义的对象中: int temperatureInCelsiusDegrees -> CelciusDeegree CelciusDeegree)

不要使用服务定位器作为依赖注入替代,它是反模式的,更多信息:http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx

票数 11
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/135971

复制
相关文章
依赖注入[3]: 依赖注入模式
IoC主要体现了这样一种设计思想:通过将一组通用流程的控制权从应用转移到框架中以实现对流程的复用,并按照“好莱坞法则”实现应用程序的代码与框架之间的交互。我们可以采用若干设计模式以不同的方式实现IoC,比如我们在《依赖注入[2]: 基于IoC的设计模式》介绍的模板方法、工厂方法和抽象工厂,接下来我们介绍一种更为有价值的IoC模式,即依赖注入(DI:Dependency Injection,以下简称DI)。
蒋金楠
2018/08/01
1.7K0
[ASP.NET Core 3框架揭秘] 依赖注入:依赖注入模式
IoC主要体现了这样一种设计思想:通过将一组通用流程的控制权从应用转移到框架之中以实现对流程的复用,并按照“好莱坞法则”实现应用程序的代码与框架之间的交互。我们可以采用若干设计模式以不同的方式实现IoC,比如我们在前面介绍的模板方法、工厂方法和抽象工厂,接下来我们介绍一种更有价值的IoC模式:依赖注入(DI:Dependency Injection)。
蒋金楠
2019/10/21
1.6K0
[ASP.NET Core 3框架揭秘] 依赖注入:依赖注入模式
[ASP.NET Core 3框架揭秘] 依赖注入:IoC模式
正如我们在《依赖注入:控制反转》提到过的,很多人将IoC理解为一种“面向对象的设计模式”,实际上IoC不仅与面向对象没有必然的联系,它自身甚至算不上是一种设计模式。一般来讲,设计模式提供了一种解决某种具体问题的方案,但是IoC既没有一个针对性的问题领域,其自身也没有提供一种可操作性的解决方案,所以我们更加倾向于将IoC视为一种设计原则。很多我们熟悉的设计模式背后都采用了IoC原则,接下来我们就来介绍几种典型的“设计模式”。
蒋金楠
2019/10/17
6370
Go:依赖注入设计模式温故
依赖注入(Dependency Injection,DI)是一种软件设计模式,用于管理对象之间的依赖关系。在DI模式中,对象的依赖关系不再由对象本身创建,而是由外部容器负责创建和管理。这使得代码更加灵活和可维护,并易于测试。
运维开发王义杰
2024/06/11
1260
Go:依赖注入设计模式温故
控制反转和依赖注入模式
一、控制反转和依赖注入两者搭配能像反射工厂那样解决程序集之间的耦合问题,下面将从Asp.Net经典的三层模式多方位的讲解控制反转和依赖注入模式,是如何帮我们进行程序集之间的解耦的。 上图是最基本的三层
郑小超.
2018/01/26
6720
使用Angular的依赖注入
Service 的表现形式是一个class,可以用来在组件中复用 比如 Http 请求获取数据,日志处理,验证用户输入等都写成Service,供组件使用。
mafeifan
2019/06/15
1K0
依赖注入和循环依赖注入
1.java bean注入的两种方式 1.1 Resource注解方式 @Resource private NestedComponent nestedComponent2; 1.2 构造器注入的方式来 private NestedComponent nestedComponent1;
oktokeep
2024/11/21
1060
设计模式: 好莱坞风格与依赖注入
当实体 e1要调用 e2.func1的时候,一般情况下直接在e1的调用处new一个e2,并调用e2的函数。这样可能会引起一些依赖。 在设计松耦合的程序时,可以使用好莱坞风格,即将e2的函数通过e1的接口注册进e1的实体中,e1会随后在合适的时候调用。 例如:
超级大猪
2020/04/29
3970
设计模式介绍:依赖注入代码示例
依赖注入是一种非常常见和有用的设计模式。让我们深入研究一下,看看它为什么如此有用,又怎么用。 依赖项注入是一种使类独立于其依赖项的编程技术。它可以将对象的创建与使用进行分离。这有助于您遵循SOLID的依赖倒置和单一责任原则。 正如我之前在关于可靠设计原则的文章中所解释的,它们的目标是提高代码的可重用性。还可以减少需要更改类的频率。依赖注入可以通过分离对象的创建和使用。这使您能够在不更改使用它们的类的情况下替换依赖类。当类的依赖项发生变化时,我们不必再承担更改类代码的风险。 依赖注入技术是 service
程序你好
2018/07/20
1.2K0
Spring IoC依赖注入:Spring提供了哪些依赖注入模式和类型呢?
Spring 容器最基本最基本的接口就是BeanFactory。BeanFactory负责配置,创建、配置Bean,其中有一个子接口ApplicationContext,也被称为Spring上下文。容器同时还管理这Bean和Bean之间的依赖关系
码农架构
2020/10/26
7280
Spring IoC依赖注入:Spring提供了哪些依赖注入模式和类型呢?
依赖注入[2]: 基于IoC的设计模式
正如我们在《控制反转》提到过的,很多人将IoC理解为一种“面向对象的设计模式”,实际上IoC自身不仅与面向对象没有必然的联系,它也算不上是一种设计模式。一般来讲,设计模式提供了一种解决某种具体问题的方案,但是IoC既没有一个针对性的问题领域,其自身没有提供一种可实施的解决方案,所以我更加倾向于将IoC视为一种设计原则。实际上很多我们熟悉的设计模式背后采用了IoC原则,接下来我们就来介绍几种典型的“设计模式”。
蒋金楠
2018/08/01
8380
在C#中使用依赖注入-工厂模式和工厂方法模式
工厂模式和工厂方法模式是设计模式中较为常见的两种模式,借助于依赖注入可以更好的发挥模式的特性。本文将通过一个业务需求的变化过程来阐述如何更好的使用设计模式与依赖注入。
newbe36524
2020/03/16
3.1K0
Spring使用注解配置依赖注入
大部分情况下,使用Spring配置依赖注入时,都是使用注解来进行配置,因为注解比xml要方便和简单。不过类似于数据源对象这种配置信息容易变更的对象除外,这种对象使用xml文件来进行配置会更适合,方便于在外部进行修改,而不需要打开代码来进行修改。
端碗吹水
2020/09/23
9510
依赖注入
“新阿姆斯特丹,夫人,”王子答道,“它的后面是洒满阳光和遍地棕榈树的巽他群岛和美丽的爪哇岛(Java)。”
宇宙之一粟
2022/05/13
8610
在Actframework中使用依赖注入
申明需要注入的对象 ActFramework通过javax.inject.Inject注解识别需要注入的对象. 你可以通过以下三种标准方式申明需要注入的对象: 字段注入 public class Foo { @Inject private Bar bar; } 构造器注入 public class Foo { private Bar bar @Inject public Foo(Bar bar) { this.bar = bar; }
老码农
2018/06/27
4690
.NET Core 依赖注入 使用技巧
.NET Core 在使用IOC后,我们不必再浪费精力在管理实例的生命周期上,交给IOC代替我们管理,减少我们成吨的代码,面向接口编程更是灵活到了极致,而IOC的三种生命周期应该怎么去使用呢,Transient(瞬态)、Scoped(作用域)、Singleton(单例)。
郑子铭
2024/04/15
2030
.NET Core 依赖注入 使用技巧
依赖注入
###1. 依赖 如果在 Class A 中,有 Class B 的实例,则称 Class A 对 Class B 有一个依赖。例如下面类 Human 中用到一个 Father 对象,我们就说类 Human 对类 Father 有一个依赖。
DencyCheng
2020/04/10
1.3K0
依赖注入
讲真的,今年就业形势相当不好,对IT从业者的专业能力要求将变得更高。近来一边忙学业,一边学习Java基础和框架源码,为不久之后的招聘做准备。
用户2987604
2020/06/15
1.7K0
.NET IoC模式依赖反转(DIP)、控制反转(Ioc)、依赖注入(DI)
依赖倒置(Dependency Inversion Principle,缩写DIP)是面向对象六大基本原则之一。他是指一种特定的的解耦形式,使得高层次的模块不依赖低层次的模块的实现细节,依赖关系被颠倒(反转),从而使得低层次模块依赖于高层次模块的需求抽象.
HueiFeng
2020/05/13
1.2K0
依赖什么啊?依赖注入……,什么注入啊?
在过去的几个月里,我和客户团队在对一个设计系统进行优化。表面上看起来这个优化工作包括两大部分:性能优化和结构重整。不过经过这几个月对十多个组件的重构之后,我们发现这两部分工作在很大程度上是同一件事的两个方面:好的设计往往可以带来更好的性能,反之亦然。这是一个非常有趣的发现,我们在讨论性能优化的时候,一个经常被忽略的因素恰恰是软件本身的设计。我们会关注文件大小,是否会有多重渲染,甚至一些细节如CSS selector的优先级等等,但是很少为了性能而审视代码的设计。另一方面,如果一个组件写的不符合S.O.L.I.D原则,我们会认为它的可扩展性不够好,或者由于文件体量过大,且职责不清而变得难以维护,但是往往不会认为糟糕的设计会对性能造成影响(也可能是由于性能总是在实现已经完成之后才被注意到)。为了更好的说明这个问题,以及如何在实践中修改我们的设计,使得代码更可能具有比较优秀的性能,我们可以一起讨论几个典型的例子。
ThoughtWorks
2021/07/29
1.9K0
依赖什么啊?依赖注入……,什么注入啊?

相似问题

什么时候使用工厂设计模式而不是依赖注入?

20

依赖注入-依赖链模式

20

使用-工厂模式与依赖项注入

10

什么时候应该使用依赖项注入(C#)

40

工厂模式和/或依赖注入?

20
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文