Что такое внедрение зависимостей?

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

Что такое внедрение зависимостей и когда /почему его следует или не следует использовать?

2779 голосов | спросил AR. 25 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 25 Sep 2008 04:28:40 +0400 2008, 04:28:40

25 ответов


0

По сути, вместо того, чтобы ваши объекты создавали зависимость или просили фабричный объект создать ее для них, вы передаете необходимые зависимости объекту извне и создаете для него чужую проблему. Этот «кто-то» является либо объектом, находящимся выше в графе зависимостей, либо инжектором зависимостей (каркасом), который создает граф зависимостей. Зависимость, которую я здесь использую, это любой другой объект, на который текущий объект должен содержать ссылку.

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

 public SomeClass() {
    myObject = Factory.getObject();
}

Это может быть проблематично, когда все, что вам нужно сделать, это запустить некоторые модульные тесты на SomeClass, особенно если myObject выполняет сложные операции с диском или сетевым доступом. Итак, теперь вы смотрите на насмешку над myObject, а также как-то перехватывает вызов фабрики. Жесткий. Вместо этого передайте объект в качестве аргумента конструктору. Теперь вы перенесли проблему в другое место, но тестирование может стать намного проще. Просто создайте фиктивный объект myObject и передайте его. Конструктор теперь будет выглядеть примерно так:

 public SomeClass (MyClass myObject) {
    this.myObject = myObject;
}

Это один стиль внедрения зависимостей - через конструктор. Возможны несколько механизмов.

  • Как отмечается в комментариях, одной из распространенных альтернатив является определение конструктора, который ничего не делает, и чтобы зависимости были введены через установщики свойств (h /t @MikeVella).
  • Мартин Фаулер описывает третью альтернативу (h /t @MarcDix), где классы явно реализуют интерфейс для зависимостей, которые они хотят ввести.

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

В 2013 году, когда я писал этот ответ, эта тема была основной на блоге тестирования Google . Это остается для меня самым большим преимуществом, так как вам не всегда может понадобиться дополнительная гибкость в дизайне среды выполнения (например, для поиска служб или аналогичных шаблонов), но вам часто нужно иметь возможность изолировать свои классы во время тестирования.

ответил wds 25 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 25 Sep 2008 04:49:32 +0400 2008, 04:49:32
0

Лучшее определение, которое я нашел до сих пор, - это один от Джеймса Шора

  

«Инъекция зависимости» - это 25 долларов   термин для концепции 5 центов. [...]   Инъекция зависимости означает предоставление   возьмите его переменные экземпляра. [...].

Существует статья Мартина Фаулера , которая также может оказаться полезной.

Внедрение зависимостей в основном предоставляет объекты, в которых нуждается объект (его зависимости), вместо того, чтобы он сам их конструировал. Это очень полезный метод для тестирования, поскольку он позволяет смоделировать или заглушить зависимости.

Зависимости могут быть введены в объекты многими способами (например, инжектор конструктора или сеттер). Можно даже использовать специализированные структуры внедрения зависимостей (например, Spring), но они, конечно, не требуются. Вам не нужны эти структуры для внедрения зависимости. Инстанцирование и передача объектов (зависимостей) в явном виде - такая же хорошая инъекция, как и внедрение через каркас.

ответил Thiago Arrais 26 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowFri, 26 Sep 2008 20:50:35 +0400 2008, 20:50:35
0

Я нашел этот забавный пример с точки зрения слабой связи :

Любое приложение состоит из множества объектов, которые взаимодействуют друг с другом для выполнения некоторых полезных задач. Традиционно каждый объект отвечает за получение своих собственных ссылок на зависимые объекты (зависимости), с которыми он сотрудничает. Это приводит к высокосвязанным классам и сложному для тестирования коду.

Например, рассмотрим объект Car.

A Car зависит от колёс, двигателя, топлива, аккумулятора и т. д. для работы. Традиционно мы определяем марку таких зависимых объектов вместе с определением объекта Car.

Без внедрения зависимостей (DI):

 class Car{
  private Wheel wh = new NepaliRubberWheel();
  private Battery bt = new ExcideBattery();

  //The rest
}

Здесь Car объект отвечает за создание зависимых объектов.

Что если мы захотим изменить тип зависимого объекта - скажем, Wheel - после начального NepaliRubberWheel() проколы? Нам нужно воссоздать объект Car с его новой зависимостью, скажем, ChineseRubberWheel(), но только Car производитель может сделать это.

Тогда что Dependency Injection делает для нас ...?

При использовании внедрения зависимостей объектам присваиваются свои зависимости во время выполнения, а не во время компиляции (время изготовления автомобиля) . Теперь мы можем изменить Wheel, когда захотим. Здесь dependency (wheel) можно быть введенным в Car во время выполнения.

После использования внедрения зависимости:

Здесь мы вводим зависимости (колесо и батарея) во время выполнения. Отсюда и термин: Внедрение зависимостей.

 class Car{
  private Wheel wh = [Inject an Instance of Wheel (dependency of car) at runtime]
  private Battery bt = [Inject an Instance of Battery (dependency of car) at runtime]
  Car(Wheel wh,Battery bt) {
      this.wh = wh;
      this.bt = bt;
  }
  //Or we can have setters
  void setWheel(Wheel wh) {
      this.wh = wh;
  }
}

Источник: Понимание внедрения зависимости

ответил gtiwari333 22 Mayam11 2011, 08:01:24
0

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

Например, рассмотрим эти предложения:

 public class PersonService {
  public void addManager( Person employee, Person newManager ) { ... }
  public void removeManager( Person employee, Person oldManager ) { ... }
  public Group getGroupByManager( Person manager ) { ... }
}

public class GroupMembershipService() {
  public void addPersonToGroup( Person person, Group group ) { ... }
  public void removePersonFromGroup( Person person, Group group ) { ... }
} 

В этом примере реализации PersonService::addManager и PersonService::removeManager потребуется экземпляр GroupMembershipService для выполнения своей работы. Без внедрения зависимостей традиционный способ сделать это - создать новый GroupMembershipService в конструкторе PersonService и использовать этот атрибут экземпляра в обеих функциях. Однако, если конструктор GroupMembershipService имеет несколько вещей, которые ему требуются, или, что еще хуже, есть некоторые инициаторы «инициализации», которые необходимо вызвать в GroupMembershipService код растет довольно быстро, а PersonService теперь зависит не только от GroupMembershipService, но и от всего остального, что GroupMembershipService зависит от. Кроме того, связь с GroupMembershipService жестко закодирована в PersonService, что означает, что вы не можете "подставить" GroupMembershipService для целей тестирования или использовать шаблон стратегии в разных частях вашего приложения.

С помощью внедрения зависимостей вместо создания GroupMembershipService в вашем PersonService, вы бы либо передали его конструктору PersonService, либо добавили свойство (геттер и сеттер) ) установить его локальный экземпляр. Это означает, что вашему PersonService больше не нужно беспокоиться о том, как создать GroupMembershipService, он просто принимает те, которые ему дали, и работает с ними. Это также означает, что все, что является подклассом GroupMembershipService или реализует GroupMembershipService интерфейс может быть "внедрен" в PersonService и PersonService не нужно знать об изменении.

ответил Adam Ness 25 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 25 Sep 2008 10:49:02 +0400 2008, 10:49:02
0

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

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

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

ответил zby 6 Jpm1000000pmThu, 06 Jan 2011 21:33:39 +030011 2011, 21:33:39
0

Давайте представим, что вы хотите пойти на рыбалку:

  • Без внедрения зависимостей вы должны позаботиться обо всем самостоятельно. Вам нужно найти лодку, купить удочку, найти приманку и т. Д. Это, конечно, возможно, но это накладывает на вас большую ответственность. С точки зрения программного обеспечения это означает, что вы должны выполнить поиск всех этих вещей.

  • С помощью инъекции зависимостей кто-то другой позаботится обо всей подготовке и предоставит вам необходимое оборудование. Вы получите («впрыснут») лодку, удочку и приманку - все готово к использованию.

ответил Olivier Liechti 22 +04002012-10-22T08:47:39+04:00312012bEurope/MoscowMon, 22 Oct 2012 08:47:39 +0400 2012, 08:47:39
0

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

 public class Car
{
    public Car()
    {
        GasEngine engine = new GasEngine();
        engine.Start();
    }
}

public class GasEngine
{
    public void Start()
    {
        Console.WriteLine("I use gas as my fuel!");
    }
}

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

 Car car = new Car();

Проблема с этим кодом, которую мы тесно связали с GasEngine, и если мы решим изменить его на ElectricityEngine, то нам нужно будет переписать класс Car. И чем больше приложение, тем больше проблем и головной боли нам придется добавить и использовать новый тип движка.

Другими словами, при таком подходе наш класс автомобилей высокого уровня зависит от класса GasEngine более низкого уровня, который нарушает принцип инверсии зависимости (DIP) от SOLID. DIP предполагает, что мы должны зависеть от абстракций, а не от конкретных классов. Чтобы удовлетворить это, мы вводим интерфейс IEngine и переписываем код, как показано ниже:

     public interface IEngine
    {
        void Start();
    }

    public class GasEngine : IEngine
    {
        public void Start()
        {
            Console.WriteLine("I use gas as my fuel!");
        }
    }

    public class ElectricityEngine : IEngine
    {
        public void Start()
        {
            Console.WriteLine("I am electrocar");
        }
    }

    public class Car
    {
        private readonly IEngine _engine;
        public Car(IEngine engine)
        {
            _engine = engine;
        }

        public void Run()
        {
            _engine.Start();
        }
    }

Теперь наш класс Car зависит только от интерфейса IEngine, а не от конкретной реализации движка. Теперь единственная хитрость заключается в том, как нам создать экземпляр Car и присвоить ему фактический класс Engine, такой как GasEngine или ElectricityEngine. Вот тут и приходит Внедрение зависимости .

    Car gasCar = new Car(new GasEngine());
   gasCar.Run();
   Car electroCar = new Car(new ElectricityEngine());
   electroCar.Run();

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

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

  

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

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

ОБНОВЛЕНИЕ: недавно посмотрел курс об EF Core от Джули Лерман, а также понравилось ее краткое определение о DI.

  

Внедрение зависимостей - это шаблон, позволяющий приложению внедрять   объекты на лету в классы, которые нуждаются в них, не заставляя тех   классы, которые будут отвечать за эти объекты. Это позволяет вашему коду быть   более слабо связаны, и Entity Framework Core подключается к этому же   система услуг.

ответил user2771704 6 J000000Thursday17 2017, 12:42:27
0

Это является наиболее простым объяснением внедрения зависимостей и Контейнер для инъекций зависимости , который я когда-либо видел:

Без внедрения зависимостей

  • Приложению требуется Foo (например, контроллер), поэтому:
  • Приложение создает Foo
  • Приложение вызывает Foo
    • Foo нужен Bar (например, служба), поэтому:
    • Foo создает Bar
    • Фу звонит в Бар
      • Бар нуждается в Bim (услуга, хранилище, …) Так что
      • Бар создает Bim
      • Бар что-то делает

С внедрением зависимости

  • Приложению нужен Foo, для которого нужен Bar, а для Bim -
  • Приложение создает Bim
  • Приложение создает Bar и передает его Bim
  • Приложение создает Foo и дает ему Bar
  • Приложение вызывает Foo
    • Фу звонит в Бар
      • Бар что-то делает

Использование контейнера внедрения зависимостей

  • Приложение нуждается в Foo так:
  • Приложение получает Foo из контейнера, поэтому:
    • Контейнер создает Bim
    • Контейнер создает Bar и передает ему Bim
    • Контейнер создает Foo и дает ему Bar
  • Приложение вызывает Foo
    • Фу звонит в Бар
      • Бар что-то делает

Внедрение зависимости и Внедрение зависимости - это разные вещи:

  • Dependency Injection - это метод для написания лучшего кода
  • Контейнер DI - это инструмент, помогающий внедрять зависимости

Вам не нужен контейнер для внедрения зависимостей. Однако контейнер может помочь вам.

ответил Trix 5 Maypm16 2016, 14:53:32
0

Разве «внедрение зависимостей» не означает просто использование параметризованных конструкторов и открытых сеттеров?

В статье Джеймса Шора приведены следующие примеры для сравнения . р>

Конструктор без внедрения зависимости:

 public class Example { 
  private DatabaseThingie myDatabase; 

  public Example() { 
    myDatabase = new DatabaseThingie(); 
  } 

  public void doStuff() { 
    ... 
    myDatabase.getData(); 
    ... 
  } 
} 

Конструктор с внедрением зависимостей:

 public class Example { 
  private DatabaseThingie myDatabase; 

  public Example(DatabaseThingie useThisDatabaseInstead) { 
    myDatabase = useThisDatabaseInstead; 
  }

  public void doStuff() { 
    ... 
    myDatabase.getData(); 
    ... 
  } 
}
ответил JaneGoodall 2 Mayam13 2013, 04:40:11
0

Что такое инъекция зависимостей (DI)?

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

DI, DIP и SOLID

В частности, в парадигме Роберта С. Мартина ТВЕРДЫЕ принципы объектно-ориентированного дизайна , DI является одной из возможных реализаций Принцип обращения зависимостей (DIP) . DIP - это D из SOLID mantra - другие реализации DIP включают в себя локатор служб и шаблоны плагинов.

Цель DIP - развязать жесткие, конкретные зависимости между классами и вместо этого ослабить связь с помощью абстракции, чего можно достичь с помощью interface, abstract class или pure virtual class, в зависимости от используемого языка и подхода.

Без DIP наш код (я назвал этот «потребительский класс») напрямую связан с конкретной зависимостью, а также часто обременен обязанностью знать, как получить и управлять экземпляром этой зависимости, то есть концептуально:

"I need to create/use a Foo and invoke method `GetBar()`"

Принимая во внимание, что после применения DIP требование ослабляется, и забота о получении и управлении сроком жизни зависимости Foo был удален:

"I need to invoke something which offers `GetBar()`"

Зачем использовать DIP (и DI)?

Разделение зависимостей между классами таким способом позволяет легко заменить этих классов зависимостей другими реализациями, которые также выполняют предварительные условия абстракции (например, зависимость может быть переключена с другой реализацией того же интерфейса ). Более того, как уже упоминали другие, возможно, самая причина разъединения классов через DIP - это позволить тестировать потребляющий класс изолированно, так как эти же зависимости теперь могут быть заглушены и /или подвергнуты насмешкам.

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

Это можно посмотреть по-разному:

  • Если необходимо сохранить контроль продолжительности жизни класса-потребителя, управление можно восстановить, введя (абстрактную) фабрику для создания экземпляров класса зависимости в класс-потребитель. Потребитель сможет получать экземпляры через Create на фабрике по мере необходимости и утилизировать эти экземпляры после завершения.
  • Или же управление временем жизни экземпляров зависимостей может быть передано контейнеру IoC (подробнее об этом ниже).

Когда использовать DI?

  • Где, вероятно, потребуется заменить зависимость эквивалентной реализацией,
  • В любое время, когда вам нужно будет выполнить модульное тестирование методов класса в изоляции от его зависимостей,
  • Если неопределенность продолжительности жизни зависимости может потребовать экспериментов (например, Эй, MyDepClass безопасна для потоков - что еслимы делаем его единичным и внедряем один и тот же экземпляр во всех потребителей?)

Пример

Вот простая реализация на C #. Учитывая приведенный ниже класс потребления:

public class MyLogger
{
   public void LogRecord(string somethingToLog)
   {
      Console.WriteLine("{0:HH:mm:ss} - {1}", DateTime.Now, somethingToLog);
   }
}

Несмотря на внешнюю безвредность, она имеет две зависимости static от двух других классов, System.DateTime и System.Console, которые не только ограничивают параметры вывода журнала (вход в консоль будет бесполезным, если никто не смотрит), но что еще хуже, трудно автоматически проверить, учитывая зависимость от недетерминированных системных часов.

Тем не менее, мы можем применить DIP к этому классу, абстрагируясь от необходимости ставить отметки времени как зависимости и связывая MyLogger только для простого интерфейса:

public interface IClock
{
    DateTime Now { get; }
}

Мы также можем ослабить зависимость от Console для абстракции, такой как TextWriter. Внедрение зависимостей обычно реализуется либо как constructor (передача абстракции зависимости в качестве параметра конструктору потребляющего класса), либо как ---- +: = 21 =: + ---- (передача зависимости через установщик Setter Injection или свойство .Net с setXyz() определено). Внедрение в конструктор является предпочтительным, поскольку это гарантирует, что класс будет в правильном состоянии после построения, и позволяет полям внутренней зависимости помечаться как {set;} (C #) или readonly (Java). Таким образом, используя инъекцию конструктора в приведенном выше примере, мы получаем следующее:

final

(Необходимо предоставить конкретный public class MyLogger : ILogger // Others will depend on our logger. { private readonly TextWriter _output; private readonly IClock _clock; // Dependencies are injected through the constructor public MyLogger(TextWriter stream, IClock clock) { _output = stream; _clock = clock; } public void LogRecord(string somethingToLog) { // We can now use our dependencies through the abstraction // and without knowledge of the lifespans of the dependencies _output.Write("{0:yyyy-MM-dd HH:mm:ss} - {1}", _clock.Now, somethingToLog); } } , который, конечно, может вернуться к Clock, и две зависимости должны быть предоставлены контейнером IoC посредством внедрения конструктора)

Можно построить автоматический модульный тест, который однозначно доказывает, что наш регистратор работает правильно, поскольку теперь у нас есть контроль над зависимостями - временем, и мы можем следить за записанным выводом:

DateTime.Now

Следующие шаги

Внедрение зависимостей неизменно связано с инверсией контейнера управления (IoC) для внедрения ( обеспечить) конкретные экземпляры зависимостей и управлять экземплярами продолжительности жизни. В процессе настройки /начальной загрузки контейнеры [Test] public void LoggingMustRecordAllInformationAndStampTheTime() { // Arrange var mockClock = new Mock<IClock>(); mockClock.Setup(c => c.Now).Returns(new DateTime(2015, 4, 11, 12, 31, 45)); var fakeConsole = new StringWriter(); // Act new MyLogger(fakeConsole, mockClock.Object) .LogRecord("Foo"); // Assert Assert.AreEqual("2015-04-11 12:31:45 - Foo", fakeConsole.ToString()); } позволяют определять следующее:

  • сопоставление между каждой абстракцией и сконфигурированной конкретной реализацией (например, "каждый раз, когда потребитель запрашивает IoC, возвращает ---- +: = 32 =: + ---- instance ")
  • политики могут быть установлены для управления жизненным циклом каждой зависимости, например, создать новый объект для каждого экземпляра-потребителя, совместно использовать экземпляр-одиночку для всех потребителей, использовать один и тот же экземпляр-зависимость только для одного потока и т. д.
  • В .Net контейнеры IoC знают о таких протоколах, как IBar, и принимают на себя ответственность ConcreteBar зависимости в соответствии с настроенным управлением продолжительностью жизни.

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

  

Ключ к DI-дружественному коду заключается в том, чтобы избегать статического соединения классов и не использовать new () для создания зависимостей

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

Но преимуществ много, особенно в способности тщательно проверить свой класс интересов.

Примечание . Создание /отображение /проекция (с помощью Disposing) DOC POCO /POJO /сериализации /Entity Graphs /Анонимные проекции JSON и др., Т.е. классы или записи «Только данные», используемые или возвращаемые из методов, не рассматриваются как зависимости (в смысле UML) и не подлежат DI. Использование new для проецирования это просто замечательно.

ответил StuartLC 28 PMpTue, 28 Apr 2015 23:17:54 +030017Tuesday 2015, 23:17:54
0

Сделать концепцию внедрения зависимостей простой для понимания. Давайте рассмотрим пример кнопки переключения для включения /выключения лампы.

Без внедрения зависимостей

Switch должен заранее знать, к какой лампочке я подключен (жестко заданная зависимость). Таким образом,

Переключатель -> Переключатель PermanentBulb //напрямую подключен к постоянной лампе, тестирование не возможно легко

Switch(){
PermanentBulb = new Bulb();
PermanentBulb.Toggle();
}

С внедрением зависимости

Коммутатор знает только, что мне нужно включать /выключать любую лампочку, которую мне передают. Таким образом,

Переключатель -> Bulb1 ИЛИ Bulb2 ИЛИ NightBulb (введенная зависимость)

Switch(AnyBulb){ //pass it whichever bulb you like
AnyBulb.Toggle();
}

Изменение James примера для переключателя и лампочки:

public class SwitchTest { 
  TestToggleBulb() { 
    MockBulb mockbulb = new MockBulb(); 

    // MockBulb is a subclass of Bulb, so we can 
    // "inject" it here: 
    Switch switch = new Switch(mockBulb); 

    switch.ToggleBulb(); 
    mockBulb.AssertToggleWasCalled(); 
  } 
}

public class Switch { 
  private Bulb myBulb; 

  public Switch() { 
    myBulb = new Bulb(); 
  } 

  public Switch(Bulb useThisBulbInstead) { 
    myBulb = useThisBulbInstead; 
  } 

  public void ToggleBulb() { 
    ... 
    myBulb.Toggle(); 
    ... 
  } 
}`
ответил wakqasahmed 28 +03002016-10-28T23:30:22+03:00312016bEurope/MoscowFri, 28 Oct 2016 23:30:22 +0300 2016, 23:30:22
0

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

  • очистка кода инициализации зависимости
  • стабильный независимо от используемой зависимости

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

Конкретной областью DI является делегирование конфигурации и инициализации зависимостей.

Пример: DI со сценарием оболочки

Если вы время от времени работаете вне Java, вспомните, как source часто используется во многих языках сценариев (Shell, Tcl и т. д., или даже import в Python, неправильно использованном для этой цели).

Рассмотрим простой скрипт dependent.sh:

#!/bin/sh
# Dependent
touch         "one.txt" "two.txt"
archive_files "one.txt" "two.txt"

Сценарий является зависимым: он не будет успешно выполнен самостоятельно (archive_files не определен).

Вы определяете archive_files в archive_files_zip.sh сценарий реализации (в этом случае используется zip):

#!/bin/sh
# Dependency
function archive_files {
    zip files.zip "[email protected]"
}

Вместо сценария реализации source -ing непосредственно в зависимом, вы используете injector.sh «контейнер», который включает оба «компонента»:

#!/bin/sh 
# Injector
source ./archive_files_zip.sh
source ./dependent.sh

archive_files зависимость только что внедрено в зависимость скрипт.

Возможно, вы внедрили зависимость, которая реализует archive_files, используя tar или xz.

Пример: удаление DI

Если бы скрипт dependent.sh использовал зависимости напрямую, этот подход назывался бы поиск зависимостей (что противоположно внедрение зависимости ):

#!/bin/sh
# Dependent

# dependency look-up
source ./archive_files_zip.sh

touch         "one.txt" "two.txt"
archive_files "one.txt" "two.txt"

Теперь проблема в том, что зависимый «компонент» должен сам выполнить инициализацию.

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

Последние слова

DI не так сильно подчеркивается и популяризируется, как в Java-фреймворках.

Но это общий подход к разделению проблем:

  • разработка приложений ( одиночный жизненный цикл выпуска исходного кода)
  • приложение развертывание ( несколько целевых сред с независимыми жизненными циклами)

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

ответил wakqasahmed 28 +03002016-10-28T23:30:22+03:00312016bEurope/MoscowFri, 28 Oct 2016 23:30:22 +0300 2016, 23:30:22
0

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

Dependency Injection (DI) означает разделение объектов, которые зависят друг от друга. Скажем, объект A зависит от объекта B, поэтому идея состоит в том, чтобы отделить эти объекты друг от друга. Нам не нужно жестко кодировать объект с использованием нового ключевого слова, а делиться зависимостями с объектами во время выполнения, несмотря на время компиляции. Если говорить о

Как работает внедрение зависимостей в Spring:

Нам не нужно жестко кодировать объект с использованием нового ключевого слова, а определить зависимость bean-компонента в файле конфигурации. Пружинный контейнер будет отвечать за подключение всех.

Инверсия контроля (IOC)

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

Два типа внедрения зависимостей:

  1. Внедрение в конструктор
  2. Сеттерная инъекция

1. Внедрение зависимостей на основе конструктора:

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

public class Triangle {

private String type;

public String getType(){
    return type;
 }

public Triangle(String type){   //constructor injection
    this.type=type;
 }
}
<bean id=triangle" class ="com.test.dependencyInjection.Triangle">
        <constructor-arg value="20"/>
  </bean>

2. Внедрение зависимостей на основе установки:

DI, основанный на установщике, выполняется контейнером, вызывающим методы setter для ваших bean-компонентов после вызова конструктора без аргументов или статического метода фабрики без аргументов для создания экземпляра вашего bean-компонента.

public class Triangle{

 private String type;

 public String getType(){
    return type;
  }
 public void setType(String type){          //setter injection
    this.type = type;
  }
 }

<!-- setter injection -->
 <bean id="triangle" class="com.test.dependencyInjection.Triangle">
        <property name="type" value="equivialteral"/>

Примечание: Хорошее практическое правило - использовать аргументы конструктора для обязательных зависимостей и методы установки для необязательных зависимостей. Обратите внимание, что если мы используем аннотацию на основе, то аннотацию @Required для установщика можно использовать для создания сеттеров в качестве необходимых зависимостей.

ответил Harleen 4 FriEurope/Moscow2015-12-04T08:50:02+03:00Europe/Moscow12bEurope/MoscowFri, 04 Dec 2015 08:50:02 +0300 2015, 08:50:02
0

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

Внедрение зависимостей - это один из шаблонов проектирования, который помогает нам создавать сложные системы более простым способом.

Мы можем наблюдать широкое применение этого шаблона в нашей повседневной жизни. Вот некоторые примеры: магнитофон, VCD, CD-привод и т. Д.

 Катушечный портативный магнитофон, середина 20-го века.

Приведенное выше изображение является изображением портативного магнитофона Reel-to-reel, середина 20-го века. источник .

Основное назначение магнитофона - записывать или воспроизводить звук.

При разработке системы требуется катушка для записи или воспроизведения звука или музыки. Есть две возможности для разработки этой системы

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

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

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

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

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

В наши дни эти концепции легли в основу хорошо известных сред программирования. Spring Angular и др. - это хорошо известные программные среды, построенные на основе этой концепции.

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

Пример для внедрения зависимости

Ранее мы писали такой код

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

Вы также можете прочитать

Разница между инверсией управления и усилением; Внедрение зависимостей

ответил Samuel J Mathew 3 52017vEurope/Moscow11bEurope/MoscowFri, 03 Nov 2017 10:36:52 +0300 2017, 10:36:52
0

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

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

DI приближает вас к принципу единой ответственности (SR), например, surgeon who can concentrate on surgery.

Когда использовать DI: я ​​бы рекомендовал использовать DI практически во всех производственных проектах (малых /больших), особенно в постоянно меняющихся бизнес-средах:)

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

ответил Anwar Husain 5 PMpTue, 05 Apr 2016 19:15:55 +030015Tuesday 2016, 19:15:55
0

Это означает, что у объектов должно быть только столько зависимостей, сколько необходимо для их работы, и зависимостей должно быть немного. Кроме того, зависимости объекта должны быть по интерфейсам, а не по «конкретным» объектам, когда это возможно. (Конкретный объект - это любой объект, созданный с помощью ключевого слова new.) Свободное связывание способствует большей возможности повторного использования, упрощению обслуживания и позволяет легко предоставлять «фиктивные» объекты вместо дорогих услуг.

«Инъекция зависимости» (DI) также известна как «Инверсия контроля» (IoC) и может использоваться в качестве метода для поощрения этой слабой связи.

Существует два основных подхода к реализации DI:

  1. Внедрение в конструктор
  2. Сеттерная инъекция

Внедрение в конструктор

Это метод передачи зависимостей объектов в его конструктор.

Обратите внимание, что конструктор принимает интерфейс, а не конкретный объект. Также обратите внимание, что возникает исключение, если параметр orderDao имеет значение null. Это подчеркивает важность получения действительной зависимости. На мой взгляд, Constructor Injection является предпочтительным механизмом для предоставления объекту его зависимостей. При вызове объекта для разработчика ясно, какие зависимости необходимо передать объекту «Person» для правильного выполнения.

Инъекция сеттера

Но рассмотрим следующий пример ... Предположим, у вас есть класс с десятью методами, которые не имеют зависимостей, но вы добавляете новый метод, который имеет зависимость от IDAO. Вы можете изменить конструктор, чтобы использовать конструктор Injection, но это может заставить вас вносить изменения во все вызовы конструктора повсюду. В качестве альтернативы, вы можете просто добавить новый конструктор, который получает зависимость, но тогда как разработчик легко узнает, когда использовать один конструктор над другим. Наконец, если создать зависимость очень дорого, зачем ее создавать и передавать конструктору, если ее можно использовать редко? «Внедрение сеттера» - это еще один метод DI, который можно использовать в таких ситуациях, как эта.

Setter Injection не заставляет зависимости передаваться в конструктор. Вместо этого зависимости устанавливаются на общедоступные свойства, предоставляемые нуждающимся объектом. Как подразумевалось ранее, основными мотиваторами для этого являются:

  1. Поддержка внедрения зависимостей без необходимости изменения конструктора унаследованного класса.
  2. Возможность создания дорогостоящих ресурсов или услуг как можно позже и только при необходимости.

Вот пример того, как будет выглядеть приведенный выше код:

public class Person {
    public Person() {}

    public IDAO Address {
        set { addressdao = value; }
        get {
            if (addressdao == null)
              throw new MemberAccessException("addressdao" +
                             " has not been initialized");
            return addressdao;
        }
    }

    public Address GetAddress() {
       // ... code that uses the addressdao object
       // to fetch address details from the datasource ...
    }

    // Should not be called directly;
    // use the public property instead
    private IDAO addressdao;
ответил Piyush Deshpande 7 Jpm1000000pmTue, 07 Jan 2014 15:45:31 +040014 2014, 15:45:31
0

Я думаю, что поскольку все написали для DI, позвольте мне задать несколько вопросов.

  1. Если у вас есть конфигурация DI, в которой все фактические реализации (не интерфейсы), которые будут внедрены в класс (например, для служб контроллера), почему это не какое-то жесткое кодирование?
  2. Что если я хочу изменить объект во время выполнения? Например, мой конфиг уже говорит, когда я создаю экземпляр MyController, введите для FileLogger как ILogger. Но я мог бы хотеть ввести DatabaseLogger.
  3. Каждый раз, когда я хочу изменить объекты, в которых нуждается мой AClass, мне нужно теперь искать в двух местах - сам класс и файл конфигурации. Как это облегчает жизнь?
  4. Если Aproperty of AClass не вводится, то сложнее его смоделировать?
  5. Возвращаясь к первому вопросу. Если использование new object () плохо, почему мы внедряем реализацию, а не интерфейс? Я думаю, что многие из вас говорят, что мы на самом деле вводим интерфейс, но конфигурация заставляет вас указать реализацию этого интерфейса ... не во время выполнения ... он жестко запрограммирован во время компиляции.

Это основано на ответе @ Adam N, опубликованном.

Почему PersonService больше не нужно беспокоиться о GroupMembershipService? Вы только что упомянули, что GroupMembership имеет несколько вещей (объектов /свойств), от которых зависит. Если в PService требуется GMService, он будет иметь свойство. Вы можете сделать это вне зависимости от того, вводили вы это или нет. Единственный раз, когда я хотел бы, чтобы его вводили, - это если бы в GMService были более конкретные дочерние классы, о которых вы не знали бы до времени выполнения. Тогда вы захотите ввести подкласс. Или, если вы хотите использовать это как синглтон или прототип. Честно говоря, в файле конфигурации есть все, что жестко запрограммировано, в зависимости от того, какой подкласс для типа (интерфейса) он собирается внедрить во время компиляции.

РЕДАКТИРОВАТЬ

Хороший комментарий Хосе Марии Арранц для DI

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

False. Направление зависимостей находится в форме XML или в виде аннотаций, ваши зависимости записываются в виде кода XML и аннотаций. XML и аннотации являются исходным кодом.

DI уменьшает связность, делая все ваши компоненты модульными (т.е. заменяемыми) и имея четко определенные интерфейсы друг с другом.

False. Вам не нужна структура DI для построения модульного кода на основе интерфейсов.

О заменяемом: с очень простым архивом .properties и Class.forName вы можете определить, какие классы можно изменять. Если ЛЮБОЙ класс вашего кода можно изменить, Java не для вас, используйте язык сценариев. Кстати, аннотации нельзя изменить без перекомпиляции.

По моему мнению, есть одна единственная причина для каркасов DI: уменьшение котельной плиты. С хорошо выполненной фабричной системой вы можете сделать то же самое, более управляемое и более предсказуемое, что и предпочитаемая вами DI-среда, DI-структуры обещают сокращение кода (XML и аннотации также являются исходным кодом). Проблема заключается в том, что это сокращение базовой платы просто реально в очень очень простых случаях (один экземпляр на класс и аналогичные), иногда в реальном мире выбор подходящего сервисного объекта не так прост, как сопоставление класса с одноэлементным объектом.

ответил Chookoos 25 +04002013-10-25T07:56:09+04:00312013bEurope/MoscowFri, 25 Oct 2013 07:56:09 +0400 2013, 07:56:09
0

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

(и ps, да, это стало чрезмерно раскрученным 25-долларовым именем для довольно простой концепции) , мой .25 центы

ответил Nikos M. 10 ThuEurope/Moscow2015-12-10T18:50:06+03:00Europe/Moscow12bEurope/MoscowThu, 10 Dec 2015 18:50:06 +0300 2015, 18:50:06
0

Популярные ответы бесполезны, потому что они определяют внедрение зависимостей таким образом, что это бесполезно. Давайте согласимся, что под «зависимостью» мы подразумеваем некоторый ранее существующий другой объект, в котором нуждается наш объект X. Но мы не говорим, что делаем «внедрение зависимостей», когда говорим

$foo = Foo->new($bar);

Мы просто вызываем эти передаваемые параметры в конструктор. Мы занимаемся этим регулярно с тех пор, как были изобретены конструкторы.

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

DI означает, что существует промежуточный уровень между вызывающей стороной и конструктором, который управляет зависимостями. Makefile - простой пример внедрения зависимостей. «Вызывающий» - это человек, набирающий «make bar» в командной строке, а «constructor» - это компилятор. Makefile указывает, что bar зависит от foo, и делает

gcc -c foo.cpp; gcc -c bar.cpp

перед выполнением

gcc foo.o bar.o -o bar

Человек, печатающий «make bar», не должен знать, что bar зависит от foo. Зависимость была введена между "make bar" и gcc.

Основная цель промежуточного уровня - не просто передать зависимости конструктору, но перечислить все зависимости в всего в одном месте и скрыть их от кодера (не заставить кодера их предоставить).

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

ответил Phil Goetz 2 J0000006Europe/Moscow 2015, 21:09:07
0

Внедрение зависимости - это одно из возможных решений того, что обычно называют требованием «обфускация зависимости». Обфускация зависимостей - это метод, позволяющий исключить «очевидную» природу из процесса предоставления зависимости классу, который требует ее, и, следовательно, каким-то образом запутать предоставление указанной зависимости указанному классу. Это не обязательно плохо. Фактически, запутывая способ, которым зависимость предоставляется классу, что-то вне класса отвечает за создание зависимости, что означает, что в различных сценариях может быть предоставлена ​​другая реализация зависимости без внесения каких-либо изменений. к классу. Это отлично подходит для переключения между рабочим и тестовым режимами (например, с использованием «фиктивной» сервисной зависимости).

К сожалению, плохая часть заключается в том, что некоторые люди предполагают, что вам нужна специализированная среда для обфускации зависимостей, и что вы как-то «меньший» программист, если вы решите не использовать конкретную среду для этого. Другой, чрезвычайно тревожный миф, по мнению многих, состоит в том, что внедрение зависимости является единственным способом достижения обфускации зависимости. Это наглядно и исторически и, очевидно, на 100% неправильно, но у вас будут проблемы с убеждением некоторых людей, что существуют альтернативы внедрению зависимости для ваших требований обфускации зависимости.

Программисты понимали требование запутывания зависимостей в течение многих лет, и многие альтернативные решения развивались как до, так и после задуманного внедрения зависимости. Существуют фабричные шаблоны, но есть также много опций, использующих ThreadLocal, в которых не требуется внедрение в конкретный экземпляр - зависимость эффективно внедряется в поток, что дает преимущество в том, что объект становится доступным (с помощью удобных статических методов получения) для любой класс, который требует этого без необходимости добавлять аннотации к классам, которые этого требуют, и настраивать сложный XML-клей, чтобы это произошло. Когда ваши зависимости требуются для персистентности (JPA /JDO или чего-либо еще), это позволяет вам гораздо легче достичь «прозрачной персистентности», а доменная модель и классы бизнес-моделей состоят исключительно из POJO (то есть, нет специфичной для каркаса /заблокированной в аннотациях). /р>

ответил Volksman 2 AMpWed, 02 Apr 2014 02:21:08 +040021Wednesday 2014, 02:21:08
0

Из книги, Обоснованный Java-разработчик: жизненно важные методы Java 7 и программирование полиглотов

  

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

ответил TastyCode 18 Maypm13 2013, 23:27:31
0

из книги Apress.Spring.Persistence.with.Hibernate.Oct.2010

  

Цель внедрения зависимости состоит в том, чтобы отделить работу   разрешение внешних программных компонентов из вашего бизнеса приложений   Логика. Без внедрения зависимостей, детали того, как компонент   Доступ к необходимым службам может быть связан с компонентами   код. Это не только увеличивает вероятность ошибок, добавляет код   раздувать, и увеличивает сложности обслуживания; это соединяет компоненты   вместе более тесно, что затрудняет изменение зависимостей, когда   рефакторинг или тестирование.

ответил BERGUIGA Mohamed Amine 28 PM00000010000003031 2015, 13:00:30
0

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

На самом деле, предположим, что в java вы создали два разных класса, как класс A и класс B, и любую функцию, доступную в классе B, которую вы хотите использовать в классе A, так что в это время можно использовать внедрение зависимостей. где вы можете создать объект одного класса в другом, таким же образом вы можете добавить целый класс в другой класс, чтобы сделать его доступным. таким образом, зависимость может быть преодолена.

Зависимость от инъекций просто склеивает два класса и в то же время, держа их отдельно.

ответил mohit sarsar 28 Maypm14 2014, 13:08:59
0

Инъекция зависимости (DI) является частью практики Принципа зависимости зависимости (DIP), которая также называется инверсией контроля (IoC). По сути, вам нужно выполнять DIP, потому что вы хотите сделать свой код более модульным и тестируемым на уровне модулей, а не только одной монолитной системой. Итак, вы начинаете идентифицировать части кода, которые можно отделить от класса и абстрагировать. Теперь реализацию абстракции нужно вводить извне класса. Обычно это можно сделать через конструктор. Таким образом, вы создаете конструктор, который принимает абстракцию в качестве параметра, и это называется внедрением зависимости (через конструктор). Для получения более подробной информации о DIP, DI и контейнере IoC вы можете прочитать Здесь

ответил kusnaditjung tjung 4 J0000006Europe/Moscow 2016, 02:34:22
0

Внедрение зависимостей - это тип реализации принципа инверсии управления , на котором основано построение Frameworks.

Frameworks , как указано в «Шаблоне проектирования» GoF, являются классами, которые реализуют логику основного потока управления, побуждая разработчика сделать это, таким образом, Frameworks реализует принцип инверсии управления.

Способ реализации как техника, а не как иерархия классов, этот принцип IoC - это просто внедрение зависимости.

DI состоит в основном в том, чтобы делегировать отображение экземпляров классов и ссылку на тип этих экземпляров на внешнюю «сущность»: объект, статический класс, компонент, каркас и т. д. ...

Экземплярами классов являются « зависимости », внешняя привязка вызывающего компонента с экземпляром класса через ссылку, это «внедрение ».

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

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

Таким образом, при разработке компонентов вы можете сосредоточиться исключительно на их архитектуре и их конкретной логике, полагаясь на интерфейсы для совместной работы с другими объектами, не беспокоясь об изменениях реализации любых типов используемых объектов /служб, в том числе при наличии одного и того же объекта вы используете будет полностью заменен (очевидно, уважая интерфейс).

ответил Ciro Corvino 18 52016vEurope/Moscow11bEurope/MoscowFri, 18 Nov 2016 01:01:43 +0300 2016, 01:01:43

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132