控制反转与dependency injection
根据马丁·福勒(Martin Fowler)的论文 ,控制反转是程序控制stream程颠倒的原理:外部源(框架,服务,其他组件)不是控制程序stream程的程序员,而是控制它。 就像我们把东西插入其他东西一样。 他提到了一个关于EJB 2.0的例子:
例如Session Bean接口定义了ejbRemove,ejbPassivate(存储到辅助存储)和ejbActivate(从被动状态恢复)。 当这些方法被调用时,你无法控制,只是他们做了什么。 容器打电话给我们,我们不叫它。
这导致了框架和库之间的区别:
控制反转是使框架与图书馆不同的一个关键部分。 图书馆本质上是一组你可以调用的函数,这些函数通常组织成类。 每个调用都会做一些工作,并将控制权返回给客户端。
我认为,DI是IOC的观点意味着一个对象的依赖是相反的:相反,它控制着它自己的依赖关系,生命周期……其他的东西是为你做的。 但是,当你用手告诉我DI时,DI不一定是IOC。 我们仍然可以有DI,也没有IOC。
然而,在本文中(来自pocoapsule,另一个IOC Framework for C / C ++),它表明由于IOC和DI,IOC容器和DI框架远远优于J2EE,因为J2EE将框架代码混合到组件,因此不会使它成为普通的Java / C ++对象(POJO / POCO)。
除dependency injection模式之外的控制容器的反转 : http : //www.pocomatic.com/docs/whitepapers/ioc-vs-di/
补充阅读,了解旧的基于组件的开发框架的问题,这导致了上面的第二篇文章: 为什么和控制反转 : http : //www.pocomatic.com/docs/whitepapers/ioc/
我的问题 :IOC和DI究竟是什么? 我很困惑。 基于pococapsule,国际奥委会是一个更重要的东西比只是颠倒对象的控制或程序员和框架。
IoC是一个通用的术语含义,而不是具有应用程序,调用框架中的方法,框架调用应用程序提供的实现。
DI是IoC的一种forms,通过构造函数/设置程序/服务查找将实现传递到对象中,对象将“依赖”以便正确执行。
没有使用DI的IoC ,例如将会是模板模式,因为只能通过子分类来改变实现。
DI框架旨在利用DI,并可以定义接口(或Java中的注释),以便于实现传递。
IoC容器是可以在编程语言之外工作的DI框架。 在某些情况下,您可以configuration哪些实现在元数据文件(例如XML)中使用,这些文件的侵入性较小。 对于一些你可以做的IoC,通常是不可能的,像在切入点注入实现。
另请参阅Martin Fowler的文章 。
总之,IoC是一个更广泛的术语,包括但不限于DI
控制反转(IoC)原本意味着任何types的编程风格,其中总体框架或运行时间控制程序stream程
在DI有了名字之前,人们开始将控制依赖的框架称为控制容器的反转(Inversion of Containers),不久之后,IoC的意义逐渐向这个特定的含义漂移:对依赖的控制反转。
控制反转 (IoC)意味着对象不会创build其他对象来执行其工作。 相反,他们从外部源(例如,xmlconfiguration文件)获取他们需要的对象。
dependency injection (DI)意味着这是在没有对象干预的情况下完成的,通常是通过构造函数参数和设置属性的框架组件。
DI是IoC的一个子集
- IoC意味着对象不会创build其他对象来完成他们的工作。 相反,他们从外部服务(例如,xml文件或单个应用程序服务)获取他们所需的对象。 我使用的IoC的2个实现是DI和ServiceLocator。
- DI意味着获取依赖对象的IoC原理是在不使用具体对象而是抽象(接口)的情况下完成的。 这使得所有的组件链可testing,导致更高层的组件不依赖于更低层的组件,只能从接口。 Mock实现这些接口。
以下是一些实现IoC的其他技巧 。
IOC(Inversion Of Controller) :控制容器来获取对象的一个实例称为Inversion of Control。,意思是代替你使用new操作符创build一个对象,让容器为你做。
DI(dependency injection) :将属性注入对象称为dependency injection。
We have three types of Dependency injection 1) Constructor Injection 2) Setter/Getter Injection 3) Interface Injection
Spring将只支持构造函数注入和Setter / Getter注入。
但是spring的文件说,他们是一样的。
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-introduction
在第一行“ IoC也被称为dependency injection(DI) ”。
IoC – 控制反转是通用的术语,与语言无关,实际上并不是创build对象,而是描述在哪个时尚对象被创build。
DI – dependency injection是一个具体的术语,我们通过使用不同的注入技术,即运行时提供对象的依赖关系。 Setter注射,构造注射或通过界面注射。
控制反转是一个devise范例,目标是对应用程序的目标组件进行更多的控制,即完成工作。
dependency injection是一种模式,用于创build其他对象所依赖的对象的实例,而无需知道在编译时将使用哪个类来提供该function。
有几个基本的技术来实现控制反演。 这些是:
- 使用工厂模式
- 使用服务定位器模式
- 使用以下任何给定types的dependency injection:
1)。 构造函数注入
2)。 安装员注射
3)。 一个接口注入
IOC表示pipe理应用程序类的外部类,外部类表示容器pipe理应用程序类之间的依赖关系。 国际奥委会的基本概念是程序员不需要创build你的对象,而是描述它们应该如何创build。
IoC容器执行的主要任务是:实例化应用程序类。 configuration对象。 组装对象之间的依赖关系。
DI是在运行时通过使用setter注入或构造函数注入来提供对象的依赖关系的过程。
既然所有的答案都强调理论,我想用第一种方法来举例说明:
假设我们正在构build一个应用程序,该应用程序包含一个订单发货后发送SMS确认消息的function。 我们将有两个类,一个负责发送SMS(SMSService),另一个负责捕获用户input(UIHandler),我们的代码如下所示:
public class SMSService { public void SendSMS(string mobileNumber, string body) { SendSMSUsingGateway(mobileNumber, body); } private void SendSMSUsingGateway(string mobileNumber, string body) { /*implementation for sending SMS using gateway*/ } } public class UIHandler { public void SendConfirmationMsg(string mobileNumber) { SMSService _SMSService = new SMSService(); _SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!"); } }
上面的实现没有错,但是有几个问题:
– )假设在开发环境中,要保存发送到文本文件而不是使用短信网关的短信,以实现此目的; 我们将最终改变(SMSService)的具体实现与另一个实现,我们正在失去的灵活性,并强迫在这种情况下重写代码。
– )我们将最终混合类的职责,我们的(UIHandler)不应该知道(SMSService)的具体实现,这应该使用“接口”在类之外完成。 当它被实现时,它将使我们能够通过交换(SMSService)与另一个实现相同接口的模拟服务来改变系统的行为,这个服务将短信保存到文本文件而不是发送到移动号码。
为了解决上述问题,我们使用将由我们的(SMSService)和新的(MockSMSService)实现的接口,基本上新的接口(ISMSService)将暴露与以下代码相同的两个服务的行为:
public interface ISMSService { void SendSMS(string phoneNumber, string body); }
然后,我们将更改我们的(SMSService)实现来实现(ISMSService)接口:
public class SMSService : ISMSService { public void SendSMS(string mobileNumber, string body) { SendSMSUsingGateway(mobileNumber, body); } private void SendSMSUsingGateway(string mobileNumber, string body) { /*implementation for sending SMS using gateway*/ Console.WriteLine("Sending SMS using gateway to mobile: {0}. SMS body: {1}", mobileNumber, body); } }
现在,我们将能够使用相同的接口创build具有完全不同实现的新的模拟服务(MockSMSService):
public class MockSMSService :ISMSService { public void SendSMS(string phoneNumber, string body) { SaveSMSToFile(phoneNumber,body); } private void SaveSMSToFile(string mobileNumber, string body) { /*implementation for saving SMS to a file*/ Console.WriteLine("Mocking SMS using file to mobile: {0}. SMS body: {1}", mobileNumber, body); } }
此时,我们可以更改(UIHandler)中的代码来轻松使用服务(MockSMSService)的具体实现,如下所示:
public class UIHandler { public void SendConfirmationMsg(string mobileNumber) { ISMSService _SMSService = new MockSMSService(); _SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!"); } }
我们已经实现了很大的灵活性,并且在代码中实现了关注的分离,但是我们仍然需要在代码库上进行更改,以在两个SMS服务之间切换。 所以我们需要实现dependency injection 。
为了达到这个目的,我们需要对我们的(UIHandler)类构造函数进行更改,通过它来传递依赖项,通过这样做,使用(UIHandler)的代码可以确定使用哪个(ISMSService)的具体实现:
public class UIHandler { private readonly ISMSService _SMSService; public UIHandler(ISMSService SMSService) { _SMSService = SMSService; } public void SendConfirmationMsg(string mobileNumber) { _SMSService.SendSMS(mobileNumber, "Your order has been shipped successfully!"); } }
现在将与类(UIHandler)交谈的UI表单负责传递接口(ISMSService)的哪个实现消耗。 这意味着我们已经颠倒了控制,(UIHandler)不再负责决定使用哪个实现,调用代码。 我们已经实现了DI的一种types的控制原理。
UI表单代码如下:
class Program { static void Main(string[] args) { ISMSService _SMSService = new MockSMSService(); // dependency UIHandler _UIHandler = new UIHandler(_SMSService); _UIHandler.SendConfirmationMsg("96279544480"); Console.ReadLine(); } }
IOC(Inversion Of Controller):控制容器获取对象的实例称为Inversion of Control。,意思是代替用new操作符创build对象,让容器为你做。
DI(dependency injection):将所需的参数(属性)从XML传递给对象(在POJO CLASS中)称为dependency injection。
DI和IOC是devise模式,主要侧重于提供组件之间的松散耦合,或者简单地说是我们分离对象之间的传统依赖关系,使得对象彼此不紧密的方式。
下面的例子,我想解释这两个概念。
以前我们正在编写这样的代码
Public MyClass{ DependentClass dependentObject /* At somewhere in our code we need to instantiate the object with new operator inorder to use it or perform some method. */ dependentObject= new DependentClass(); dependentObject.someMethod(); }
通过dependency injection,dependency injection器将负责对象的实例化
Public MyClass{ /* Dependency injector will instantiate object*/ DependentClass dependentObject /* At somewhere in our code we perform some method. The process of instantiation will be handled by the dependency injector */ dependentObject.someMethod(); }
上述将控件赋予其他控件(例如容器)进行实例化和注入的过程可以称为控制反转(inversion of control),IOC容器为我们注入依赖的过程称为dependency injection(dependency injection)。
IOC是程序控制stream程颠倒的原理:程序员不是通过控制程序stream程来控制stream程,而是通过减less程序员的开销来控制stream程,而程序注入依赖的过程被称为DI
这两个概念共同为我们提供了一种编写更灵活,可重用和封装代码的方法,这使得它们成为devise面向对象解决scheme中的重要概念。
让我们从SOLID的D开始,看看Scott Millett的书“Professional ASP.NET Design Patterns”中的DI和IoC:
依赖倒置原理(DIP)
DIP就是把你的类从具体的实现中分离出来,让它们依赖于抽象的类或者接口。 它将编码的口号提升到了一个接口而不是一个实现,通过确保你没有紧密耦合到一个实现来增加系统内部的灵活性。
dependency injection(DI)和控制反转(IoC)
与DI密切相关的是DI原则和IoC原则。 DI是通过构造函数,方法或属性提供低级或依赖类的行为。 与DI一起使用时,这些相关类可以转换为接口或抽象类,这将导致松散耦合的系统具有高度可testing性并易于更改。
在IoC中 ,与程序编程相比,系统的控制stream程是反向的。 一个例子是一个IoC容器 ,其目的是将服务注入客户端代码,而不需要客户端代码指定具体的实现。 在这种情况下,被颠倒的控制是客户获得服务的行为。
Millett,C(2010)。 专业的ASP.NETdevise模式。 威利出版社 7-8。
// ICO,DI,10年前,这是他们的方式:
public class AuditDAOImpl implements Audit{ //dependency AuditDAO auditDAO = null; //Control of the AuditDAO is with AuditDAOImpl because its creating the object public AuditDAOImpl () { this.auditDAO = new AuditDAO (); } }
现在春季3,4或最新的下面
public class AuditDAOImpl implements Audit{ //dependency //Now control is shifted to Spring. Container find the object and provide it. @Autowired AuditDAO auditDAO = null; }
总的来说,控制从旧代码耦合到像Spring这样的框架使得对象可用。 所以这就是我所知道的IOC和dependency injection,就像我们使用Constructor或者setter将依赖对象注入到另一个对象时一样。 注入基本上意味着将其作为parameter passing。 在spring,我们有基于XML&注解的configuration,我们定义了bean对象,并且使用Constructor或者setter注入方式来传递依赖对象。
IOC(Inversion of Control)基本上是去除依赖关系的devise模式概念,将它们解耦为使stream程非线性化,让容器/或其他实体pipe理依赖关系的提供。 它实际上遵循好莱坞校长“不要打电话给我们,我们会打电话给你”。 所以总结一下差异。
控制反转: – 这是一个通用的术语来分离依赖和委托他们的供应,这可以通过几种方式(事件,委托等)来实现。
dependency injection: – DI是IOC的一个子types,由构造函数注入,setter注入或方法注入实现。
以下文章非常整齐地描述这一点。
https://www.codeproject.com/Articles/592372/Dependency-Injection-DI-vs-Inversion-of-Control-IO