что такое inversion of control

Инверсия управления/Inversion of Control

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

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

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

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

Теперь между этими двумя программами большая разница в потоке управления — в частности, в управлении временем, когда вызываются методы process_name и process_quest. В примере с коммандной строкой я контролирую, когда эти методы вызываются, но в примере с оконным приложением нет. Вместо этого я передаю контроль оконной системе (команда Tk.mainloop). Далее она решает, когда вызвать мои методы, основываясь на связях, которые я настроил при создании формы. Управление инвертировано — управляют мной, а не я управляю фреймворком. Это явление и называется инверсией управления (также известно как Принцип Голливуда — «Не звони нам, мы сами позвоним тебе» — Hollywood Principle — «Don’t call us, we’ll call you»).

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

Ральф Джонсон и Брайан Фут.

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

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

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

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

EJB-компоненты являются хорошим примером такого стиля инверсии управления. При разработке сессионного компонента(session bean), вы можете реализовать различные методы, которые вызываются EJB-контейнером в различных точках/состояниях жизненного цикла. Например, у интерфейса SessionBean есть методы ejbRemove, ejbPassivate (сохранен во вторичное хранилище) и ejbActivate (восстановлен из пассивного состояния). Вы не можете управлять вызовом этих методов, только тем, что они делают. Контейнер вызывает нас, а не мы вызываем его.

Примечание перевода, пример:

Это сложные случаи инверсии управления, но вы столкнетесь с этим в гораздо более простых ситуациях. Шаблонный метод является хорошим примером: супер-класс определяет поток управления, субклассы наследуются от него переопределяя методы или реализуя абстрактные методы. Например, в JUnit, код фреймворка вызывает методы setUp и tearDown для вас, чтобы создавать и очищать ваш тест. Происходит вызов, ваш код реагирует — это снова инверсия управления.

Примечание перевода, пример:

В наши дни, в связи с ростом количества IoC-контейнеров, существует некоторая путаница со смыслом инверсии управления. Некоторые люди путают общий принцип с конкретными стилями инверсии управления (такими как внедрение зависимостей), которые эти контейнеры используют. Все это немного запутанно (и иронично), так как IoC-контейнеры, как правило, рассматриваются в качестве конкурента EJB, но EJB использует инверсию управления.

Этимология: Насколько я могу судить, термин инверсии управления впервые появился на свет в работе Джонсона и Фута Designing Reusable Classes, опубликованной в журнале Object-Oriented Programming в 1988 году. Работа является одной из тех, что в возрасте хороши — ее можно прочитать даже спустя пятнадцать лет. Они считают, что они взяли этот термин откуда-то еще, но не могут вспомнить откуда. Затем термин втерся в объектно-ориентированное сообщество и вновь появился в книге Gang of Four. Более красивый синоним «Принцип Голливуда», кажется, берет начало в работе Ричарда Свита в Mesa в 1983 году. В списке целей разработки он пишет: Не звони нам, мы сами позвоним тебе (Закон Голливуда): инструмент должен организовать Тахо, чтобы предупредить его, когда пользователь захочет передать какое-то событие инструменту, вместо того, чтобы принимать модель «запросить у пользователя команду и выполнить ее». Джон Влиссидес пишет колонку о C++, которая несет в себе хорошее объяснение концепции под названием «Принцип Голливуда». (Спасибо Брайану Футу и Ральфу Джонсону за помощь с этимологией).

Источник

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

что такое inversion of control. Смотреть фото что такое inversion of control. Смотреть картинку что такое inversion of control. Картинка про что такое inversion of control. Фото что такое inversion of control

Вступление

Наверняка первый вопрос, который возник у вас при взгляде на заголовок, был «Шта?«. На самом деле я просто перевел фразу «Инверсия управления, внедрение зависимости» в Google Translate на китайский, а затем обратно. Зачем? Затем, что на мой взгляд, это хорошая иллюстрация того, что происходит на самом деле. Люди вокруг путают, коверкают и извращают эти понятия. По долгу службы я провожу много интервью, и 90% того, что я слышу, когда задаю вопрос про DI — честно говоря, откровенный бред. Я сделал поиск по Хабру и нашел несколько статей, которые пытаются раскрыть эту тему, но не могу сказать, что они мне сильно понравились (ладно, ладно, я проглядел только три первых страницы, каюсь). Здесь же на Хабре я встречал в комментариях такую расшифровку IoC, как Injection of Container. Кто-то всерьез предполагает, что есть некий механизм инъекции контейнеров, который сосуществует где-то рядом с DI, и, видимо, даже делает нечто похожее. Только с контейнерами. Мда. На самом деле понять внедрение зависимости очень просто, надо всего лишь…

Удивительно, но факт — эта штука со «всего лишь. » действительно работает! Иначе вы бы здесь не оказались, не так ли?

Ричард Фейнман был удивительным рассказчиком, умевшим ясно и доступно объяснять весьма сложные вещи (посмотрите, хотя бы, это видео). Джоэл Спольски считает, что по-настоящему умный программист обязательно должен уметь изъясняться на человеческом языке (а не только на Си). Ну и, наверное, практически каждому известен афоризм Альберта Эйнштейна: «Если вы что-то не можете объяснить шестилетнему ребёнку, вы сами этого не понимаете«. Конечно же, я не собираюсь сравнивать вас с шестилетними детьми, но тем не менее постараюсь рассказать про DI, IoC и еще один DI максимально просто и понятно.

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

Инверсия управления (Inversion of Control)

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

Однако, к сожалению, выходные заканчиваются, наступает понедельник, и приходится идти на работу (если, конечно, она у вас есть). По условиям трудового договора вы должны быть на месте в 8 утра. Вы работаете до полудня. Потом у вас перерыв на обед, а затем еще четыре часа кипучей деятельности. Наконец, в 17:00 вы выбираетесь из офиса и отправляетесь домой, где снова можете расслабиться и вмонтировать пивандрия. Чувствуете разницу? Вы больше не управляете своим дневным расписанием, это делает кое-кто другой — ваш работодатель.

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

Но в один прекрасный день в кабинет входит босс и сообщает пренеприятнейшее известие — консоль больше не в моде, миром правят графические интерфейсы, а значит все надо переделать. Будучи современным и гибким (речь не только о ваших занятиях йогой) программистом, вы сразу принимаетесь за внесение изменений. Для этого вы подключаете GUI-фреймворк и пишете код обработки событий. Если нажата вот эта кнопка, то надо сделать то-то и то-то. А если пользователь изменил свой выбор в выпадающем списке, то не обойтись без вот этого и этого. Все идет хорошо, но тут вы понимаете, что раньше было как-то по-другому. А кто, собственно, вызывает эти обработчики событий, которые вы так усердно программируете? Кто вообще определяет, куда и когда нажал пользователь? Что вообще происходит? Где мои носки? GUI-фреймворк оказался явно хитрее, чем вы думали, и перехватил у вас управление потоком выполнения приложения.

Это и есть Inversion of Control — очень абстрактный принцип, постулирующий факт задания потока выполнения некой внешней по отношению к вам сущностью.

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

В качестве домашнего задания поразмышляйте, почему Джефф Сазерленд настаивает на том, что SCRUM — это именно фреймворк, а не методология.

Инверсия зависимости (Dependency Inversion)

Это та самая буква D в аббревиатуре SOLID — принцип, говорящий о том, что:

Проблема здесь заключается в том, что класс Foo зависит от конкретного класса Bar. По той или иной причине — в целях расширяемости, переиспользуемости или тестируемости ради — может встать задача их разделить. Согласно принципу инверсии зависимости для этого следует ввести между ними промежуточную абстракцию.

Диаграмма UML наглядно демонстрирует оба варианта.

что такое inversion of control. Смотреть фото что такое inversion of control. Смотреть картинку что такое inversion of control. Картинка про что такое inversion of control. Фото что такое inversion of control

Сложности начинаются, когда спрашиваешь, а где же здесь, собственно, инверсия? Основополагающая идея, без понимания которой невозможно ответить на этот вопрос, заключается в том, что интерфейсы принадлежат не своим реализациям, а использующим их клиентам. Имя интерфейса IBar вводит в заблуждение и заставляет рассматривать связку IBar + Bar как единое целое. В то же время истинным владельцем IBar является класс Foo, и если принять это во внимание, то направление связи между Foo и Bar действительно обратится вспять.

что такое inversion of control. Смотреть фото что такое inversion of control. Смотреть картинку что такое inversion of control. Картинка про что такое inversion of control. Фото что такое inversion of control

Внедрение зависимости (Dependency Injection)

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

Чтобы избавить класс Foo от такой неприятной обязанности, хорошо было бы вынести код инстантинации куда-то в другое место и инкапсулировать его там (поскольку все мы чрезвычайно прагматичны и не любим ничего писать дважды). Сделать это можно двумя способами — используя либо Service Locator, либо Dependency Injection.

Service Locator — это такой реестр соответствия абстракций и их реализаций. Вы скармливаете ему интересующий вас интерфейс, а в ответ получаете готовый экземпляр конкретного класса. Выглядит это примерно так:

Нюанс заключается в том, что класс Foo теперь совершенно не зависит от класса Bar, но по-прежнему управляет его инстантинацией. Как мы уже знаем, избежать этого можно инвертировав поток управления, т.е. передав оное управление в руки некоего внешнего механизма. Dependency Injection и является таким механизмом, реализуемым в виде фреймворков под названием IoC-контейнеры:

Заключение

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

Подытожим. Мы используем Dependency Inversion, чтобы разделить модули абстракцией, Dependency Injection, чтобы избавиться от инстантинации вручную, а реализуем это посредством фреймворка, построенного по принципу Inversion of Control. И ничто из этого не является синонимами, поэтому IoC-контейнеры — яркий пример того, как можно намертво всех запутать с помощью одного единственного неудачного термина.

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

Источник

Русские Блоги

Инверсия управления (IoC) в Spring и внедрение зависимостей (DI)

Что такое Ioc (инверсия управления)

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

Преимущества архитектуры IoC

Общие механизмы реализации IoC включают: шаблон разработки стратегии, шаблон Service Locator, шаблон Factory, внедрение зависимостей (DI).

Что такое DI (внедрение зависимостей)

Поведение соединения объектов с другими объектами или «внедрения» объектов в другие объекты контролируется системой управления, а не самим объектом.

Контейнер IoC Spring

В рамках Spring ApplicationContext Интерфейс представляет собой контейнер Ioc, который в основном отвечает за создание экземпляров, настройку, загрузку компонентов и их жизненный цикл.

Весенняя пара ApplicationContext Интерфейс предоставляет несколько реализаций

Для возможности загрузки контейнер можно настроить в виде XML или аннотаций.

Внедрение зависимостей Spring

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

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

Контейнер будет вызывать конструктор с параметрами при создании экземпляра bean-компонента, и каждый параметр представляет зависимость, которую мы хотим установить.

Spring проанализирует каждый параметр, сначала по типу, но когда он не определен, он будет проанализирован в соответствии с именем параметра (имя параметра получается через ParameterNameDiscoverer, который реализуется ASM)

Внедрение зависимостей на основе сеттера (внедрение зависимостей на основе сеттера)

Spring сначала создает экземпляр Bean, а затем вызывает метод Setter, который необходимо ввести для выполнения инъекции.

Внедрение зависимостей на основе полей

Когда Spring собирает Beans, он также реализует внедрение, записывая домены сущностей с помощью метода и механизма Java после конструктора и метода Setter.

Такой способ инъекции кажется более простым и понятным; но этот метод не стоит продвигать по следующим причинам:

Зависимая модель автоматического впрыска

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

Автоматически загружать Bean в зависимости от типа атрибута и BY_NAME Точно так же Spring найдет подходящую инъекцию bean-компонента в соответствии с типом атрибута, и если есть несколько bean-компонентов одного типа, будет выдано исключение.

На основе автоматической автоматической инъекции конструктора Spring найдет тот же тип Bean, что и параметр для достижения инъекции, в соответствии с параметрами конструктора.

Компонент отложенной загрузки

Spring по умолчанию создает и настраивает множество singleton beans в начальном процессе, но вы можете передать lazy-init Атрибут для предотвращения такого поведения

Источник

Инверсия управления и Внедрение зависимостей (IoС & DI)

Давайте рассмотрим что такое инверсия управления в языке программирования C#, для чего она нужна и какие проблемы он решает. Где можно применять данный шаблон, а где это будет излишним. Также давайте обратим внимание на её отличия от внедрение зависимостей, а также чем похожи IoС & DI.

Что такое Инверсия управления и Внедрение зависимостей (IoС & DI)

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

Инверсия управления (Inversion of Control, IoC) это определенный набор рекомендаций, позволяющих проектировать и реализовывать приложения используя слабое связывание отдельных компонентов. То есть, для того чтобы следовать принципам Инверсии управления нам необходимо:

Одним из видов конкретной реализации данных рекомендаций является механизм Внедрения зависимостей (Dependency Injection, DI). Он определяет две основные рекомендации:

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

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

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

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

Существует несколько конкретных паттернов Внедрения зависимостей:

Давайте рассмотрим примеры реализации данных паттернов.

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

Реализация без инверсия управления

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

Теперь нам только и осталось создать экземпляр нашего майнера и запустить процесс майнинга.

В результате мы получим следующее:

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

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

Для начала добавим интерфейс для алгоритмов поиска хешей.

Создадим новый класс алгоритма Ethash и изменим существующий SHA256.

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

Изменим класс майнер следующим образом.

Как видите, теперь майнер не зависит от конкретного алгоритма, а принимает только интерфейс как аргумент конструктора.

Теперь нам немного нужно изменить вызов майнера в консольном приложении.

что такое inversion of control. Смотреть фото что такое inversion of control. Смотреть картинку что такое inversion of control. Картинка про что такое inversion of control. Фото что такое inversion of control

Внедрение зависимостей через свойство

что такое inversion of control. Смотреть фото что такое inversion of control. Смотреть картинку что такое inversion of control. Картинка про что такое inversion of control. Фото что такое inversion of control

Внедрение зависимостей через аргумент метода

что такое inversion of control. Смотреть фото что такое inversion of control. Смотреть картинку что такое inversion of control. Картинка про что такое inversion of control. Фото что такое inversion of control

Исходный код также можно посмотреть в репозитории https://github.com/shwanoff/DependencyInjection.

IoC-контейнер

Также хотелось бы упомянуть о IoC-контейнерах. IoC-контейнер (IoC-container) — это своеобразный фреймворк, позволяющий реализовывать Внедрение зависимостей более лаконичным способом, избавляя от рутины. Существует много различных IoC-контейнеров. Вот некоторые наиболее популярные из них:

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

Рекомендую также изучить статью SOLID в объектно-ориентированном программировании. Инверсия управления входит в набор этих принципов, поэтому целесообразно изучить остальные. А еще подписывайтесь на группу ВКонтакте, Telegram и YouTube-канал. Там еще больше полезного и интересного для программистов.

Похожее

Похожие записи

Lazy command C# | Паттерн Ленивая команда C#

Источник

IoC, DI, IoC-контейнер — Просто о простом

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

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

Теория

Для меня взаимосвязь между IoC и DI такая же как между Agile и Scrum, т.е.
Inversion of Control (инверсия управления) — это некий абстрактный принцип, набор рекомендаций для написания слабо связанного кода. Суть которого в том, что каждый компонент системы должен быть как можно более изолированным от других, не полагаясь в своей работе на детали конкретной реализации других компонентов.
Dependency Injection (внедрение зависимостей) — это одна из реализаций этого принципа (помимо этого есть еще Factory Method, Service Locator).
IoC-контейнер — это какая-то библиотека, фреймворк, программа если хотите, которая позволит вам упростить и автоматизировать написание кода с использованием данного подхода на столько, на сколько это возможно. Их довольно много, пользуйтесь тем, чем вам будет удобно, я продемонстрирую все на примере Ninject.

Практика

Согласно подходу инверсии управления если у нас есть клиент, который использует некий сервис, то он должен делать это не напрямую, а через посредника, своего рода аутсорсинг.
что такое inversion of control. Смотреть фото что такое inversion of control. Смотреть картинку что такое inversion of control. Картинка про что такое inversion of control. Фото что такое inversion of control
То как технически это будет сделано и определяет каждая из реализаций подхода IoC.
Мы будем использовать DI, на простом примере:
Скажем есть некий класс, который создает расписание, а другой класс его отображает (их как правило много, скажем один для десктоп-приложения, другой для веба и т.д.).
Если бы мы ничего не знали о IoC, DI мы бы написали что-то вроде этого:

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

Мы, например, воспользуемся внедрением зависимостей (DI) для того, чтобы разорвать этот клубок стальных ниток — сделаем связь между этими классами более слабой, добавив прослойку в виде интерфейса IScheduleManager. И будем разрешать ее одним из способов техники DI, а именно Constructor Injection (помимо этого есть Setter Injection и Method Injection — если в двух словах, то везде используется интерфейс вместо конкретного класса, например в типе свойства или в типе аргумента метода):

И далее там где мы хотим воспользоваться нашим классом для отображения расписания мы пишем:

Вот уже почти идеально, но что если у нас много различных ScheduleViewer, разбросанных по проекту, которые использует всегда именно ScheduleManager (придется его руками каждый раз создавать) и/или мы хотим как-либо настроить поведение, так что бы в одной ситуации везде использовать ScheduleManager, а в другой скажем AnotherScheduleManager и т.д.
Решить эту проблему как раз и призваны IoC-контейнеры.

IoC-контейнеры

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

Теперь везде где требуется IScheduleManager будет подставляться ScheduleManager.
2. Создаем сам контейнер, указывая его конфигуратор:

Контейнер сам создаст экземпляр класса ScheduleManager, вызовет конструктор ScheduleViewer и подставит в него свежесозданный экземпляр ScheduleManager.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *