[dependency-injection] Инверсия контроля против инъекции зависимостей


7 Answers

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

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

До того, как у ДИ было имя, люди начали ссылаться на фреймворки, которые управляют зависимостями как инверсия контрольных контейнеров, и вскоре значение IoC постепенно дрейфовало к этому конкретному значению: инверсия контроля над зависимостями.

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

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

Question

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

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

Это приводит к различию между каркасом и библиотекой:

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

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

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

Инверсия контрольных контейнеров, отличных от шаблона инъекции зависимостей : http://www.pocomatic.com/docs/whitepapers/ioc-vs-di/

Дополнительное чтение, чтобы понять, в чем проблема со старой платформой разработки на основе компонентов, что приводит ко второму документу, приведенному выше: Почему и что такое инверсия управления : http://www.pocomatic.com/docs/whitepapers/ioc/

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




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

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




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

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

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



Я нашел лучший пример на Dzone.com который очень полезен для понимания реальных различий между IOC и DI

«IoC - это когда у вас есть кто-то другой, создающий для вас объекты». Поэтому вместо того, чтобы писать в своем коде ключевое слово «new» (например, MyCode c = new MyCode ()), объект создается кем-то другим. Этот «кто-то еще» обычно называют контейнером IoC. Это означает, что мы передаем rrsponsibility (control) в контейнер, чтобы получить экземпляр объекта, называется Inversion of 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.

Dzone.com и прочитать полную статью DI





source

IoC ( I nversion o f C ontrol): - Это общий термин и реализован несколькими способами (событиями, делегатами и т. Д.).

DI ( D ependency I njection): - DI является подтипом IoC и реализуется путем инъекции конструктора, инъекции установщика или инъекции интерфейса .

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

  • Впрыск сеттера
    • Сеттер-основанный DI реализуется путем вызова методов setter в бобах пользователя после вызова конструктора без аргумента или статического заводского метода без аргументов для создания экземпляра их компонента.
  • Инъекция конструктора
    • Диск конструктора основан на вызове конструктора с рядом аргументов, каждый из которых представляет собой соавтор.



Начнем с D SOLID и посмотрим на DI и IoC из книги Скотта Миллетта «Профессиональные шаблоны проектирования ASP.NET»:

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

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

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

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

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

Millett, C (2010). Профессиональные шаблоны проектирования ASP.NET. Wiley Publishing. 7-8.




IOC (Inversion of Controller) : Предоставление контроля контейнеру для получения экземпляра объекта называется Inversion of Control. Означает вместо того, чтобы вы создавали объект с помощью нового оператора, пусть контейнер сделает это для вас.

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

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

Весна будет поддерживать только инжекцию конструктора и инъекцию Setter / Getter.




IOC (Inversion of Control) представляет собой концепцию шаблона проектирования для удаления зависимостей и их развязывания для обеспечения нелинейности потока и позволяет контейнеру / или другому объекту управлять предоставлением зависимостей. Это фактически следует за Голливудским директором «Не называй нас, мы позвоним тебе». Итак, суммируя различия.

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

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

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

source




Related