Инверсия Управления против инъекции зависимостей


по словам статья написана Мартином Фаулером, инверсия управления-это принцип, при котором поток управления программой инвертируется: вместо программиста, управляющего потоком программы, внешние источники (фреймворк, сервисы, другие компоненты) берут на себя управление ею. Как будто мы подключаем что-то к чему-то другому. Он привел пример о EJB 2.0:

например интерфейс сеансового компонента определяет ejbRemove, ejbPassivate (хранится во вторичном хранилище), и ejbActivate (восстановлен из пассивного состояния государство.) Вы не можете контролировать, когда эти методы называются, просто какие так и есть. Контейнер зовет нас, мы не называй это.

Это приводит к разнице между фреймворком и библиотекой:

инверсия управления является ключевой частью что делает каркас отличается от библиотека. Библиотека-это по сути набор функций, которые можно вызывать, в эти дни обычно организованный в занятия. Каждый вызов выполняет некоторую работу и возвращает управление клиенту.

Я думаю, точка зрения, что DI является IOC, означает, что зависимость объекта инвертирована: вместо этого он контролирует свои собственные зависимости, жизненный цикл... что-то еще делает это для вас. Но, как вы сказали мне о Ди руками, Ди не обязательно МОК. У нас все еще может быть Ди и нет МОК.

однако в этой статье (из pococapsule, другой структуры IOC для C/C++) он предполагает, что из-за IOC и DI контейнеры IOC и DI-фреймворки намного превосходят J2EE, поскольку J2EE смешивает код фреймворка в компоненты, тем самым не делая его простым старым объектом Java/C++ (POJO/POCO).

инверсия контейнеров управления, отличных от шаблона инъекции зависимостей (архивная ссылка)

дополнительное чтение, чтобы понять, в чем проблема со старой компонентной основой разработки, которая приводит к второй документ выше: почему и что из инверсии управления (архивная ссылка)

У Меня Вопрос: что такое МОК и Ди? Я в замешательстве. Основанный на pococapsule, IOC является чем-то более значительным, чем просто инвертировать контроль между объектами или программистами и фреймворками.

19 372

19 ответов:

МОК это общий термин, означающий, что вместо того, чтобы приложение, вызывайте методы в рамках, платформа вызывает реализации, предоставляемые приложением.

DI - это форма IoC, где реализации передаются в объект через конструкторы/сеттеры/сервисные запросы, от которых объект будет "зависеть", чтобы вести себя правильно.

МОК без использования DI, например, был бы шаблон потому что реализация может быть изменена только через подкласс.

DI Framework предназначены для использования DI и могут определять интерфейсы (или аннотации в Java), чтобы упростить передачу в реализациях.

IoC-Контейнеры являются di фреймворки, которые могут работать за пределами языка программирования. В некоторых вы можете настроить, какие реализации использовать в файлах метаданных (например, XML), которые являются менее инвазивными. С некоторыми вы можете сделать МОК это обычно было бы невозможно, как ввести реализацию в pointcuts.

см. также статья Мартина Фаулера.

короче говоря, МОК-это гораздо более широкий термин, который включает, но не ограничивается, DI

термин инверсия управления (IoC) первоначально означал любой вид стиля программирования, где общий фреймворк или время выполнения контролировали поток программы

прежде чем у DI появилось имя, люди начали ссылаться на фреймворки, которые управляют зависимостями как инверсия из контрольных контейнеров, и вскоре значение МОК постепенно дрейфовало к этому конкретному значению: инверсия контроля над Зависимости.

инверсия управления (IoC) означает, что объекты не создают другие объекты, на которые они полагаются для выполнения своей работы. Вместо этого они получают необходимые им объекты из внешнего источника (например, из файла конфигурации xml).

Инъекции Зависимостей (DI) означает, что это делается без вмешательства объекта, обычно с помощью компонента framework, который передает параметры конструктора и свойства набора.

DI является подмножеством IoC

  • МОК означает, что объекты не создают другие объекты, на которые они полагаются для выполнения своей работы. Вместо этого они получают необходимые им объекты из Внешней службы (например, xml-файл или отдельная служба приложений). 2 реализации IoC, которые я использую, являются DI и ServiceLocator.
  • DI означает, что принцип IOC получения зависимого объекта выполняется без использования конкретных объектов, но абстракций (интерфейсов). Это делает все компоненты цепочки тестируемыми, потому что компонент более высокого уровня не зависит от компонента более низкого уровня, только от интерфейса. Издевается над реализацией этих интерфейсов.

вот некоторые другие методы для достижения МОК.

МОК (инверсия управления): предоставление управления контейнеру для получения экземпляра объекта называется инверсией управления., означает, что вместо того, чтобы вы создаете объект с помощью оператора new, пусть контейнер сделает это за вас.

DI (инъекция зависимости): способ введения свойств в объект называется инъекцией зависимостей.

We have three types of Dependency injection
    1)  Constructor Injection
    2)  Setter/Getter Injection
    3)  Interface Injection

Spring будет поддерживать только инъекцию конструктора и сеттер / Геттер Инъекция.

enter image description here
источник

МОК (яnversion of Control): - это общий термин и реализуется несколькими способами (события, делегаты и т. д.).

DI (Dependency яnjection) :- Ди-суб-типа МОК и реализуется с помощью инъекция конструктора, инъекция сеттера или интерфейс инъекция.

но Spring поддерживает только следующие два типа:

  • Сеттер Инъекций
    • setter-based DI реализуется путем вызова методов setter на бобах пользователя после вызова конструктора без аргументов или статического Заводского метода без аргументов для создания экземпляра их Боба.
  • Конструктор Инъекций
    • конструктор на основе DI реализуется путем вызова конструктор с несколькими аргументами, каждый из которых представляет соавтора.Используя это, мы можем проверить, что введенные бобы не являются нулевыми и быстро отказывают(время компиляции), поэтому при запуске самого приложения мы получаем NullPointerException: bean does not exist. Инъекция конструктора-это лучшая практика для инъекции зависимостей.

но весенняя документация говорит, что они одинаковы.

http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-introduction

в первой строке"IoC также известен как инъекция зависимости (DI)".

МОК - инверсия управления-это общий термин, независимый от языка, он фактически не создает объекты, а описывает, каким образом создается объект.

DI - инъекция зависимостей-это конкретный термин, в котором мы предоставляем зависимости объекта во время выполнения с использованием различных методов инъекции, а именно. Впрыска сеттера, впрыска конструктора или Впрыской интерфейса.

инверсия управления-это парадигма проектирования с целью предоставления большего контроля целевым компонентам вашего приложения, тем, которые выполняют работу.
Инъекция зависимостей-это шаблон, используемый для создания экземпляров объектов, на которые полагаются другие объекты, не зная во время компиляции, какой класс будет использоваться для предоставления этой функции.

Существует несколько основных методов реализации инверсии управления. Эти являются:

  • использование заводского шаблона
  • Использование шаблона локатора служб
  • С помощью инъекции зависимостей любого типа:

    1). Инъекция конструктора
    2). Инъекция сеттера
    3). Инъекция интерфейса

поскольку все ответы подчеркивают теорию, я хотел бы продемонстрировать на примере первого подхода:

предположим, что мы создаем приложение, которое содержит функцию отправки 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!");
    }
}

выше реализация не является неправильным, но есть несколько вопросов:
- ) Предположим, что в среде разработки вы хотите сохранить SMSs, отправленный в текстовый файл, вместо использования SMS-шлюза, чтобы достичь этого; мы в конечном итоге изменим конкретную реализацию (SMSService) с другой реализацией, мы теряем гибкость и вынуждены переписывать код в этом случае.
- ) Мы в конечном итоге смешиваем обязанности классов, наш (UIHandler) никогда не должен знать о конкретной реализации (SMSService), это должно быть сделано вне классов с использованием "интерфейсов". Когда это будет реализовано, это даст нам возможность изменить поведение системы путем замены (SMSService), используемого с другой макетной службой, которая реализует тот же интерфейс, эта служба сохранит SMSs в текстовый файл вместо отправки в 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. Поэтому нам нужно реализовать Инъекции Зависимостей.

для этого нам нужно реализовать изменение в нашем конструкторе класса (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), отвечает за то, какую реализацию интерфейса (ISMSService) использовать. Это означает, что мы инвертировали элемент управления, (UIHandler) больше не несет ответственности за то, какую реализацию использовать, вызывающий код делает. Мы реализовали инверсия управления принцип, который Ди является одним из видов оно.

код формы пользовательского интерфейса будет выглядеть следующим образом:

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

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

        Console.ReadLine();
    }
}

МОК указывает,что внешние классы управляют классами приложения, а внешние классы означают, что контейнер управляет зависимостью между классами приложения. основная концепция МОК это программист не нужно создавать свои объекты, но описать, как они должны быть созданы.

основные задачи, выполняемые контейнером IoC: чтобы создать экземпляр класса приложения. для настройки объекта. чтобы собрать зависимости между объектами.

DI процесс предоставления зависимостей объекта во время выполнения с помощью инъекции сеттера или инъекцию конструктора.

МОК(инверсия управления) : предоставление управления контейнеру для получения экземпляра объекта называется инверсией управления., значит вместо вас создаете объект с помощью новый оператор, пусть контейнер сделает это за вас.

DI (инъекция зависимостей): передача необходимых параметров(свойств) из XML в объект (в классе POJO) называется инъекцией зависимостей.

IOC (инверсия управления)-это в основном концепция шаблона проектирования для удаления зависимостей и их развязки , чтобы сделать поток нелинейным, и позволить контейнеру / или другому объекту управлять предоставлением зависимостей. Это на самом деле следует за голливудским директором "не звоните нам, мы позвоним вам". Итак, суммируя различия.

инверсия управления : - это общий термин для разделения зависимостей и делегирования их подготовки , и это может быть реализовано в несколькими способами (события, делегаты и т. д.).

инъекция зависимостей: - DI является подтипом IOC и реализуется путем инъекции конструктора, инъекции сеттера или инъекции метода.

следующая статья описывает это очень аккуратно.

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

инверсия управления-это общий принцип проектирования архитектуры программного обеспечения, который помогает создавать многоразовые модульные программные платформы, которые просты в обслуживании.

это принцип проектирования, в котором поток управления "получен" из универсальной библиотеки или многоразового кода.

чтобы понять это лучше, давайте посмотрим, как мы использовали код в наши ранние дни кодирования. В процедурных / традиционных языках бизнес-логика обычно управляет потоком приложения и "вызывает" общий или многоразовый код/функции. Например, в простом консольном приложении Мой поток управления управляется инструкциями моей программы, которые могут включать вызовы некоторых общих многоразовых функций.

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, платформа уже будет доступна для создания элементов пользовательского интерфейса, таких как кнопки, меню, окна и диалоговые окна. Когда я пишу бизнес-логику своего приложения, это будут события framework, которые будут вызывать мой код бизнес-логики (когда событие запускается), а не наоборот.

хотя код фреймворка не знает о моей бизнес-логике, он все равно будет знать, как вызвать мой код. Это достигается с помощью событий/делегатов, обратные вызовы и т. д. Здесь управление потоком "перевернуто".

Итак, вместо зависимости потока управления от статически связанные объекты, поток зависит от общего графа объектов и отношений между различными объектами.

Dependency Injection-это шаблон проектирования, реализующий принцип IoC для разрешения зависимостей объектов.

проще говоря, когда вы пытаетесь написать код, вы будете создавать и использовать различные классы. Один класс (класс A) может использовать другие классы (класс B и/или D). Итак, класс B и D являются зависимостями класса A.

простая аналогия будет классный автомобиль. Автомобиль может зависеть от других классов, таких как двигатель, Шины и многое другое.

инъекция зависимостей предполагает, что вместо зависимых классов (класс Car здесь), создающих свои зависимости (класс Engine и класс Tyre), класс должен быть введен с конкретным экземпляром зависимости.

давайте разберемся с более практическим примером. Считайте, что вы пишете свой собственный текстовый редактор. Среди прочего, вы можете иметь проверку орфографии, которая обеспечивает пользователь с возможностью проверить опечатки в его тексте. Простой реализацией такого кода может быть:

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 и найдет список опечаток, которые он покажет пользователю.

все, кажется, работает отлично, пока в один прекрасный день, когда один пользователь начинает писать французский язык в Редакторе.

обеспечить поддержку для более языки, нам нужно больше проверяющих орфографию. Вероятно, французский, немецкий, испанский и т. д.

здесь мы создали тесно связанный код с"английским" средством проверки орфографии, тесно связанным с нашим классом TextEditor, что означает, что наш класс TextEditor зависит от английского средства проверки орфографии или, другими словами, EnglishSpellCheker является зависимостью для 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.

вы можете прочитать полную статью здесь

DI и МОК два шаблон что главным образом фокусируя на обеспечивать свободное соединение между компонентами, или просто способ, которым мы отделяем обычные отношения зависимости между объектами, чтобы объекты не были плотно друг к другу.

на следующих примерах я пытаюсь объяснить обе эти концепции.

ранее мы пишем код, как это

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

С помощью инъекции зависимостей инжектор зависимостей позаботится о создании экземпляров объектов

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 вводит зависимость для нас, можно назвать инъекцией зависимости.

МОК является принцип, где поток управления программа инвертируется: вместо программиста, управляющего потоком программы, программа контролирует подачу путем уменьшение накладных расходов к программисту.и процесс, используемый программой для введения зависимости, называется DI

Также Рекомендуем снимать показания.

что такое инъекция зависимостей?

вы также можете проверить один из моих подобных ответов здесь

разница между инверсией управления и инъекцией зависимостей

давайте начнем С D SOLID и посмотрим на DI и IoC из книги Скотта Миллетта "Professional ASP.NET шаблоны проектирования":

принцип инверсии зависимостей (DIP)

The DIP это все об изоляции ваших классов от бетона реализации и зависят от абстрактных классов или межфазные границы. Это способствует мантре кодирования к интерфейсу, а не чем реализация, которая увеличивает гибкость внутри системы обеспечение того, что вы не тесно связаны с одной реализацией.

инъекция зависимостей (DI) и инверсия контроля (IoC)

близко соединенный к погружению принцип Ди и принцип МОК. DI является ли акт поставки низкого уровня или зависимого класса через a конструктор, метод или свойство. Использованный совместно с Ди, эти зависимые классы могут быть инвертированы в интерфейсы или абстрактные классы это приведет к слабосвязанным системам, которые являются высоко тестируемыми и легко изменить.

на МОК, поток управления системы инвертируется по сравнению с процедурным программированием. Примером этого является МОК контейнер, целью которого является внедрение сервисов в клиентский код не имея клиентского кода, определяющего конкретную реализацию. Элемент управления в этом случае, который инвертируется, является актом получение клиентом услуга.

Millett, C (2010). Профессионал ASP.NET шаблоны проектирования. Уайли Паблишинг. 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, насколько я знаю, и инъекция зависимостей, как вы знаете, когда мы вводим зависимый объект в другой объект с помощью конструктора или сеттеров . Inject в основном означает передачу его в качестве аргумента. В весна у нас есть конфигурация на основе XML и аннотаций, где мы определяем объект bean и передаем зависимый объект с помощью конструктора или стиля инъекции setter.

Я нашел лучший пример на Dzone.com что действительно полезно, чтобы понять реальное различие между МОК и DI

" IoC-это когда у вас есть кто-то еще, кто создает объекты для вас."Поэтому вместо написания ключевого слова" new " (например, MyCode c=new MyCode ()) в вашем коде объект создается кем-то другим. Этот "кто-то еще" обычно называют контейнером МОК. Это означает, что мы передаем rrsponsibility (control )в контейнер, чтобы получить экземпляр объекта называется инверсией управления., значит, вместо того, чтобы вы создаете объект с помощью нового оператора, пусть контейнер сделает это за вас.

   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.

Читайте полную статью МОК и Читать полную статью DI

1) DI является дочерним - > obj зависит от родительского-obj. Глагол зависит имеет важное значение. 2) IOC является дочерним->obj выполнять под платформой. где платформа может быть школа, колледж, танцы. Здесь perform-это действие с различным значением под любым поставщиком платформы.

практический пример: -

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

'

- AB

инверсия управления

Основные Понятия

вот неформальное определение МОК: "МОК-это когда кто-то другой создает для вас объекты."Вместо того, чтобы писать "новый" ключевое слово в вашем коде, объект создан кем-то другим. Этот "кто-то еще" обычно называют контейнером МОК.

Это простое объяснение иллюстрирует некоторые очень важные идеи:

  1. это называется IoC, потому что управление объектом инвертируется. Это не программист, но кто-то другой, кто контролирует объект.
  2. МОК является относительным в том смысле, что он применяется только к некоторым объектам приложения. Таким образом, для некоторых объектов может быть МОК, тогда как другие находятся под прямым контролем программист.

Инъекции Зависимостей Инъекция зависимостей стала одним из краеугольных камней современного программного обеспечения инженерия, как она есть фундаментальный, чтобы позволить надлежащее тестирование. Проще говоря, имея DI-это противоположность жестко закодированных зависимостей.

зависимость может быть введена несколькими способами, как параметр в конструкторе или через метод" set".