控制反转vs依赖注入

根据马丁·福勒写的论文,控制反转是程序控制流反转的原理:不是程序员控制程序流,而是外部源(框架、服务、其他组件)控制程序流。就像我们把一个东西插入另一个东西。他提到了一个关于EJB 2.0的例子:

例如Session Bean接口 定义ejbRemove, ejbPassivate (存储到二级存储),以及 ejbActivate(从被动恢复 状态)。你不能控制时间 这些方法被调用,只是什么 他们做的事。集装箱召唤我们,我们

这就导致了framework和library的区别:

控制反转是一个关键的部分 框架与框架的区别是什么 图书馆。图书馆本质上是一个 一组你可以调用的函数, 这些日子通常组织成 类。每次调用都要做一些工作

.返回控制到客户端

我认为,DI是IOC的观点,意味着对象的依赖关系是倒置的:而不是它控制自己的依赖关系、生命周期……其他东西可以帮你。但是,正如你告诉我的DI by hands, DI不一定是IOC。我们仍然可以有DI,没有IOC。

然而,在本文中(来自pococapsule, C/ c++的另一个IOC框架),它指出,由于IOC和DI, IOC容器和DI框架要比J2EE优越得多,因为J2EE将框架代码混合到组件中,因此它不是普通的旧Java/ c++对象(POJO/POCO)。

依赖注入模式以外的控制反转容器(存档链接)

额外的阅读来理解旧的基于组件的开发框架的问题,这导致了上面的第二篇论文:为什么和什么反转的控制(档案链接)

IOC和DI到底是什么?我很困惑。基于pococapsule, IOC不仅仅是对象或程序员与框架之间控制的反转。

389313 次浏览

# EYZ0 (IoC)模式,是关于提供callback中的任何(它"实现"和/或控制反应),而不是我们自己直接行动(换句话说,反转和/或重定向控制到外部处理器/控制器)。

例如,不是让应用程序调用图书馆(也称为工具包)提供的实现,而是让框架调用应用程序提供的实现。

# EYZ0 (DI)模式是IoC模式的一个更具体的版本,其中实现通过构造函数/设置器/服务查找传递到对象中,对象将“依赖”它们以正确地行为。

每个DI实现都可以被认为是IoC,但不应该叫它IoC,因为实现依赖注入比实现回调更难(不要用一般术语“ioc&c”来降低你产品的价值;相反)。

例如,不使用DI的IoC将是模板模式,因为实现只能通过子类化来更改。

DI框架是设计用来使用DI的,并且可以定义接口(或Java中的注释),以便于在实现中传递。

IoC容器是可以在编程语言之外工作的DI框架。在某些情况下,您可以配置在侵入性较小的元数据文件(如XML)中使用哪些实现。有一些你可以做IoC,这通常是不可能的,比如在切入点注入一个实现。

看看这个马丁·福勒的文章

简而言之,IoC是一个更广泛的术语,包括但不限于DI

术语控制反转(IoC)最初指的是任何一种编程风格 框架或运行时控制的程序流

在DI有名字之前,人们开始把管理依赖项的框架称为反转 控制容器,很快,IoC的含义逐渐漂移到特定的含义:对依赖项的控制反转

控制反转 (IoC)意味着对象不创建它们所依赖的其他对象来完成工作。相反,他们从外部来源(例如,xml配置文件)获取所需的对象。

依赖注入 (DI)意味着这是在没有对象干预的情况下完成的,通常由传递构造函数参数和设置属性的框架组件完成。

国际奥委会表示外部类管理应用程序的类,外部类表示容器管理应用程序类之间的依赖关系。 国际奥委会的基本概念是程序员不需要创建你的对象,而是描述他们应该如何创建

IoC容器执行的主要任务是: 实例化应用程序类。配置对象。

.

.

是通过使用setter注入或构造函数注入在运行时提供对象依赖关系的过程。

但是spring文档说它们是一样的。

< a href = " http://docs.spring。io / spring / docs /经常/ spring-framework-reference / htmlsingle / # beans-introduction noreferrer“rel = > http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/ beans-introduction < / >

在第一行“IoC也称为依赖注入(DI)”中。

DI是IoC的一个子集

  • 国际奥委会表示对象不创建它们所依赖的其他对象来完成工作。相反,它们从外部服务(例如,xml文件或单个应用程序服务)获取所需的对象。我使用的IoC的两个实现是DI和ServiceLocator。
  • 意味着获取依赖对象的IoC原则不使用具体对象,而是使用抽象(接口)。这使得所有组件链都是可测试的,因为高级组件不依赖于低级组件,只依赖于接口。mock实现这些接口。

# EYZ0。

国际奥委会 -控制反转是一个通用术语,与语言无关,它实际上不是创建对象,而是描述如何创建时尚对象。

依赖注入是一个具体的术语,我们通过使用不同的注入技术,即Setter注入、构造函数注入或接口注入,在运行时提供对象的依赖关系。

控制反转是一种设计范式,其目标是为应用程序的目标组件提供更多的控制,即完成工作的组件 依赖注入是一种模式,用于创建其他对象依赖的对象实例,而在编译时不知道哪个类将被用于提供该功能

实现控制反转有几种基本技术。这些都是:

  • 使用工厂模式
  • 使用服务定位器模式
  • 使用任何给定类型的依赖注入:

    1).构造函数注入
    2). setter注入
    3).接口注入

IOC(控制反转):将获取对象实例的控制权交给容器被称为控制反转,这意味着你不用使用new操作符来创建对象,而是让容器来为你做这件事。

DI(依赖注入):向对象注入属性的方法称为依赖注入

我们有三种类型的依赖注入:

  1. 构造函数注入
  2. Setter和Getter注入
  3. 接口注入

Spring只支持构造函数注入Setter和Getter注入

将控制权交给容器以获取对象实例称为控制反转。这意味着你不用使用新的操作符来创建对象,而是让容器来为你做这件事。

将所需的参数(属性)从XML传递到一个对象(在POJO类中)称为依赖注入。

让我们从SOLID的D开始,看看Scott Millett的《Professional ASP》一书中的DI和IoC。NET设计模式:

依赖倒置原理(DIP)

是关于将你的类与具体隔离 实现和让它们依赖于抽象类或 接口。它推崇的是对接口进行编码 而不是实现,它通过

.

.

依赖注入(DI)和控制反转(IoC)

与DIP紧密相连的是DI原则和IoC原则。是通过类提供低级类或依赖类的行为 构造函数、方法或属性。与DI一起使用,这些 依赖类可以被反转为接口或抽象类 这将导致松散耦合的系统,高度可测试和

国际奥委会中,系统的控制流是反向的 与过程式编程相比。一个例子是IoC 容器,其目的是向客户端代码中注入服务 而不需要客户端代码指定具体实现。 在这个例子中被反转的控制是

.客户端正在获取服务

米勒特,C(2010)。专业的ASP。NET设计模式。威利出版社,7-8。

因为所有的答案都强调理论,我想用一个例子优先的方法来证明:

假设我们正在构建一个应用程序,其中包含在订单发出后发送SMS确认消息的功能。 我们将有两个类,一个负责发送SMS (SMSService),另一个负责捕获用户输入(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)与另一个实现相同接口的模拟服务交换来改变系统的行为,该服务将短信保存到文本文件中,而不是发送到mobileNumber

为了解决上述问题,我们使用接口,这些接口将由我们的(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);
}
}

现在我们将能够创建新的模拟服务(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服务之间切换。所以我们需要实现< em >依赖注入< / em >

为了实现这一点,我们需要对(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是其中的一种。

UI表单代码如下所示:

class Program
{
static void Main(string[] args)
{
ISMSService _SMSService = new MockSMSService(); // dependency


UIHandler _UIHandler = new UIHandler(_SMSService);
_UIHandler.SendConfirmationMsg("96279544480");


Console.ReadLine();
}
}

国际奥委会是两个设计模式,它们主要关注提供组件之间的松散耦合,或者仅仅是一种解耦对象之间传统依赖关系的方法,这样对象之间就不会紧密相连。

通过下面的例子,我试图解释这两个概念。

以前我们是这样写代码的

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注入,依赖注入器将负责对象的实例化

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();
}

上述将控件交给其他容器(例如容器)进行实例化和注入的过程可以称为控制反转,IOC容器为我们注入依赖项的过程可以称为依赖项注入。

IOC是程序的控制流颠倒的原则:而不是由程序员控制程序的流,程序通过减少程序员的开销来控制流程。和# EYZ1

这两个概念一起工作为我们提供了一种编写更加灵活、可重用和封装的代码的方法,这使得它们在设计面向对象的解决方案时成为重要的概念。

也推荐阅读。

什么是依赖注入?< / >

你也可以在这里查看我的一个类似的答案

控制反转与amp;依赖注入< / >

//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 ();
}
}

现在有了Spring 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和依赖注入我们使用构造函数或setter将依赖对象注入到另一个对象。注入基本上意味着将它作为参数传递。春季我们有XML &基于注释的配置,我们定义bean对象,并通过构造函数或setter注入样式传递依赖对象。

IOC(控制反转)基本上是一个设计模式概念,删除依赖项并将它们解耦以使流非线性,并让容器/或另一个实体管理依赖项的供应。它实际上遵循了好莱坞的原则“不要打电话给我们,我们会打电话给你”。 总结一下不同点。< / p >

控制反转:这是一个通用术语,用于解耦依赖关系并委托它们的供应,这可以通过几种方式实现(事件,委托等)。

依赖注入:—DI是IOC的一种子类型,通过构造函数注入、setter注入或方法注入实现。

下面的文章对此进行了非常简洁的描述。

https://www.codeproject.com/Articles/592372/Dependency-Injection-DI-vs-Inversion-of-Control-IO

< p > # EYZ0 < br > # EYZ0 < / p >

国际奥委会 (nversion # eyz2f# eyz3control):这是一个通用术语,并以多种方式实现(事件,委托等)。

(Dependency njection): DI是IoC的子类型,由构造函数注入、setter注入或接口注入实现。

但是,Spring只支持以下两种类型:

  • < >强Setter注入
    • 基于setter的DI是通过在调用无参数构造函数或无参数静态工厂方法来实例化他们的bean之后调用用户bean上的setter方法来实现的。
    • 李< / ul > < / >
    • < >强构造函数注入
      • 基于构造函数的DI是通过调用带有许多参数的构造函数来实现的,每个参数代表一个合作者。使用它,我们可以验证注入的bean不是空的,并且快速失败(在编译时失败,而不是在运行时失败),因此在启动应用程序本身时,我们得到NullPointerException: bean does not exist。构造函数注入是注入依赖项的最佳实践。
      • 李< / ul > < / >

我在Dzone.com上找到了最好的例子,这对理解IOC和DI之间的真正区别非常有帮助

" IoC是当你让别人为你创建对象时。"因此,与其在代码中写入“new”关键字(例如,MyCode c=new MyCode()),对象是由其他人创建的。这个“其他人”通常被称为IoC容器。这意味着我们将责任(控制)移交给容器以获得对象的实例,这称为控制反转。 这意味着你不用new操作符来创建对象,而是让容器来为你创建对象

   DI(Dependency Injection):  Way of injecting properties to an object is
called
Dependency injection.
We have three types of Dependency injection
1)  Constructor Injection
2)  Setter/Getter Injection
3)  Interface Injection
Spring will support only Constructor Injection and Setter/Getter Injection.

阅读全文阅读全文

1) DI是Child->obj依赖于parent-obj。动词“视情况而定”很重要。 2) IOC是Child->obj在一个平台下执行。平台可以是学校,大学,舞蹈班。这里的perform是在任何平台提供程序下具有不同含义的活动 < p >实际的例子: ' < / p >

//DI
child.getSchool();
//IOC
child.perform()// is a stub implemented by dance-school
child.flourish()// is a stub implemented by dance-school/school/

ab

控制反转是软件体系结构的一种通用设计原则,它有助于创建易于维护的可重用的模块化软件框架。

它是一种设计原则,其中控制流是从通用编写的库或可重用代码中“接收”的。

为了更好地理解它,让我们看看我们在早期是如何编写代码的。在过程式/传统语言中,业务逻辑通常控制应用程序的流程,并“调用”通用或可重用的代码/函数。例如,在一个简单的控制台应用程序中,我的控制流是由我的程序的指令控制的,这可能包括对一些一般可重用函数的调用。

print ("Please enter your name:");
scan (&name);
print ("Please enter your DOB:");
scan (&dob);


//More print and scan statements
<Do Something Interesting>


//Call a Library function to find the age (common code)
print Age

与IoC相反,框架是“调用”业务逻辑的可重用代码。

例如,在基于windows的系统中,已经有一个框架可以创建按钮、菜单、窗口和对话框等UI元素。当我编写应用程序的业务逻辑时,将是框架的事件调用我的业务逻辑代码(当事件触发时),而不是相反。

尽管框架的代码不知道我的业务逻辑,但它仍然知道如何调用我的代码。这是通过使用事件/委托、回调等实现的。这里的流量控制是“反向的”。

因此,控制流不是依赖于静态绑定的对象,而是依赖于整个对象图和不同对象之间的关系。

依赖注入是一种实现IoC原则来解决对象依赖关系的设计模式。

简单地说,当您尝试编写代码时,您将创建和使用不同的类。一个类(类A)可以使用其他类(类B和/或D),因此,类B和类D是类A的依赖关系。

一个简单的类比是类Car。汽车可能依赖于其他类别,如引擎、轮胎等。

依赖注入建议不是依赖类(这里是类Car)创建它的依赖项(类Engine和类Tyre),而是应该用依赖项的具体实例注入类。

让我们用一个更实际的例子来理解。假设您正在编写自己的TextEditor。除此之外,您还可以使用拼写检查器,为用户提供检查文本中的错别字的工具。这样一个代码的简单实现可以是:

Class TextEditor
{


//Lot of rocket science to create the Editor goes here


EnglishSpellChecker objSpellCheck;
String text;


public void TextEditor()


{


objSpellCheck = new EnglishSpellChecker();


}


public ArrayList <typos> CheckSpellings()
{


//return Typos;


}


}

乍一看,一切都很美好。用户将编写一些文本。开发人员将捕获文本并调用CheckSpellings函数,并找到他将显示给用户的拼写错误列表。

一切似乎都很好,直到有一天,一个用户开始在编辑器中编写法语。

为了提供对更多语言的支持,我们需要更多的拼写检查器。可能是法语、德语、西班牙语等。

在这里,我们创建了一个紧密耦合的代码,其中“English”SpellChecker与我们的TextEditor类紧密耦合,这意味着我们的TextEditor类依赖于EnglishSpellChecker,换句话说,English spellcheker是TextEditor的依赖项。我们需要消除这种依赖关系。此外,我们的文本编辑器需要一种方法来保存任何拼写检查器的具体引用,基于开发人员在运行时的自由裁量权。

因此,正如我们在DI的介绍中看到的,它建议类应该注入它的依赖项。因此,将所有依赖项注入到被调用的类/代码应该是调用代码的责任。所以我们可以把代码重构为

interface ISpellChecker
{


Arraylist<typos> CheckSpelling(string Text);


}


Class EnglishSpellChecker : ISpellChecker


{


public override Arraylist<typos> CheckSpelling(string Text)


{


//All Magic goes here.


}


}






Class FrenchSpellChecker : ISpellChecker


{


public override Arraylist<typos> CheckSpelling(string Text)


{


//All Magic goes here.


}


}

在我们的例子中,TextEditor类应该接收ISpellChecker类型的具体实例。

现在,可以在构造函数、公共属性或方法中注入依赖项。

让我们尝试使用构造函数DI来改变我们的类。修改后的TextEditor类看起来像这样:

Class TextEditor


{


ISpellChecker objSpellChecker;


string Text;






public void TextEditor(ISpellChecker objSC)


{


objSpellChecker = objSC;


}






public ArrayList <typos> CheckSpellings()


{


return objSpellChecker.CheckSpelling();


}


}

因此,在创建文本编辑器时,调用代码可以将适当的拼写检查器类型注入到TextEditor的实例中。

您可以阅读完整的文章在这里

关于这个问题,我想说维基已经提供了详细易懂的解释。我引用这里最重要的。

实现IoC

在面向对象编程中,有几种基本的技术来实现 实现控制反转。这些都是:< / p >
  1. 使用服务定位器模式 构造函数注入参数注入Setter注入 接口注入;李< / >
  2. 使用上下文化查找;
  3. 采用模板法设计模式;
  4. 使用策略设计模式

至于依赖注入

依赖注入是一种技术,其中一个对象(或静态的 方法)提供了另一个对象的依赖关系。依赖关系是 可以使用的对象(服务)。注入是传递 对使用它的依赖对象(客户端)的依赖

IoC概念最初出现在过程式编程时代。因此,从历史背景来看,IoC谈到了所有权控制的反转——,即谁拥有以所需顺序调用函数的责任——无论是函数本身还是应该将它反转到一些外部实体。

然而,一旦OOP出现,人们开始在OOP上下文中讨论IoC,其中应用程序除了控制流之外,还关注对象的创建及其关系。这样的应用程序想要对象创建的所有权(而不是控制流),需要一个容器来负责对象创建,对象生命周期&注入应用程序对象的依赖关系,从而避免应用程序对象创建其他具体对象。

从这个意义上讲,DI与io# EYZ0不同,因为它不是关于控制流的,而是a kind of Io*,即对象创建的所有权倒置。

我解释DI和IoC的方式有什么错?< / >

我认为这个想法可以清楚地展示,而不需要进入面向对象的杂草,这似乎混淆了这个想法。

// dependency injection
function doSomething(dependency) {
// do something with your dependency
}


// in contrast to creating your dependencies yourself
function doSomething() {
dependency = getDependencySomehow()
}


// inversion of control
application = makeApp(authenticate, handleRequest, sendResponse)
application.run(getRequest())


// in contrast to direct control or a "library" style
application = makeApp()
request = application.getRequest()


if (application.authenticate(request.creds)) {
response = application.handleRequest(request)
application.sendResponse(response)
}

如果您倾斜头部并眯起眼睛,就会发现DI是IoC的一种特殊实现,具有特定的关注点。您不是将模型和行为注入到应用程序框架或更高阶操作中,而是将变量注入到函数或对象中。

Ioc - dip - di

  1. 控制反转(IOC)
  2. 依赖倒置原理(DIP)
  3. 依赖注入(DI)

1- 国际奥委会:描述某些软件架构设计的一个方面的抽象原理,其中系统的控制流与过程式编程相比是反向的。

2-:是面向对象编程(OOP)原理(D of SOLID)。

EYZ0:是一种软件设计模式,它实现了控制反转,并允许程序设计遵循依赖反转原则。

enter image description here # EYZ0 < / p >

与其直接对比DI和IoC,不如从头开始:每个重要的应用程序都依赖于其他代码段。

所以我写一个类,MyClass,我需要调用一个方法YourService…我需要以某种方式获取YourService的实例。最简单、最直接的方法是自己实例化它。

# EYZ0

直接实例化是获取依赖项的传统(过程性)方法。但是它有许多缺点,包括MyClassYourServiceImpl的紧密耦合,这使得我的代码难以更改和测试。MyClass并不关心YourService的实现是什么样子的,所以MyClass不想负责实例化它。

我更希望的责任从MyClassMyClass之外。最简单的方法是将实例化调用(new YourServiceImpl();)移动到其他类中。我可以将这个类命名为Locator,或者Factory,或者其他任何名称;但重点是MyClass不再负责YourServiceImpl。我颠倒了依赖关系。太好了。

问题是,MyClass仍然负责调用定位器/工厂/等等。因为我反转依赖关系所做的全部工作就是插入一个中间人,所以现在我耦合到中间人(即使我没有耦合到中间人给我的具体对象)。

我并不真正关心依赖项来自何处,因此我宁愿不负责进行检索依赖项的调用。仅仅反转依赖本身是不够的。我想反转整个过程的控制。

我需要的是插入MyClass的一段完全独立的代码(称其为框架)。然后我剩下的唯一责任就是声明我对YourService的依赖。框架可以负责确定在何处、何时以及如何获取实例,并向MyClass提供它需要的东西。最好的部分是,MyClass不需要知道框架。框架可以控制这个依赖连接过程。现在我已经反转了控件(在反转依赖项之上)。

MyClass连接到框架中有不同的方法。注入就是这样一种机制,通过这种机制,我只需声明一个希望框架提供的字段或参数,通常是在框架实例化MyClass时。

我认为所有这些概念之间的关系层次比这个线程中的其他图表所显示的要稍微复杂一些;但其基本思想是,这是一种等级关系。我认为这与在野外浸泡是同步的。

 Dependency Acquisition Hierarchy of Acquisition

DIP vs DI vs IoC

[依赖倒置原则]SOLID<一口>[对]< /一口>的一部分,它要求你使用抽象而不是实现

在这种情况下,外部对象负责内部的逻辑。哪一种方法使您拥有更动态和更可测试的方法

class A {
B b


//injecting B via constructor
init(b: B) {
self.b = b
}
}

控制反转(IoC)非常高级的定义,更多的是关于控制流。最好的例子是Inversion of Control(IoC) Container or Framework<一口>[对]< /一口>。例如,GUI是一个框架,你没有一个控制,你能做的一切只是实现框架的接口,当一些动作发生在框架中时,它会被调用。这样,控制权就从应用程序转移到了正在使用的框架中

Dip + di

class A {
IB ib


init(ib: IB) {
self.ib = ib
}
}

你也可以使用:

更复杂的例子

依赖规则多层/模块结构

伪代码:

interface InterfaceInputPort {
func input()
}


interface InterfaceOutputPort {
func output()
}


class A: InterfaceOutputPort {


let inputPort = B(outputPort: self)


func output() {
print("output")
}
}


class B: InterfaceInputPort {
let outputPort: InterfaceOutputPort


init(outputPort: InterfaceOutputPort) {
self.outputPort = outputPort
}


func input() {
print("input")
}
}