Внедрение зависимости
Внедрение зависимости (англ. Dependency injection, DI) — процесс предоставления внешней зависимости программному компоненту. Является специфичной формой «инверсии управления» (англ. Inversion of control, IoC), когда она применяется к управлению зависимостями. В полном соответствии с принципом единой обязанности объект отдаёт заботу о построении требуемых ему зависимостей внешнему, специально предназначенному для этого общему механизму[1].
JNDI-запросы сервиса, когда объект запрашивает сервис по имени, реализуют внедрение зависимости лишь частично.
Содержание
Настоящее внедрение зависимости
При настоящем внедрении зависимости объект пассивен и не предпринимает вообще никаких шагов для выяснения зависимостей, а предоставляет для этого сеттеры и/или принимает своим конструктором аргументы, посредством которых внедряются зависимости[1].
Принцип работы
<imagemap>: неверное или отсутствующее изображение |
В этом разделе не хватает ссылок на источники информации. Информация должна быть проверяема, иначе она может быть поставлена под сомнение и удалена.
Вы можете отредактировать эту статью, добавив ссылки на авторитетные источники. Эта отметка установлена 13 ноября 2013 года. |
Работа фреймворка, обеспечивающая внедрение зависимости, описывается следующим образом. Приложение, независимо от оформления, исполняется внутри контейнера IoC, предоставляемого фреймворком. Часть объектов в программе по-прежнему создается обычным способом языка программирования, часть создается контейнером на основе предоставленной ему конфигурации.
Условно, если объекту нужно получить доступ к определенному сервису, объект берет на себя ответственность за доступ к этому сервису: он или получает прямую ссылку на местонахождение сервиса, или обращается к известному «сервис-локатору» и запрашивает ссылку на реализацию определенного типа сервиса. Используя же внедрение зависимости, объект просто предоставляет свойство, которое в состоянии хранить ссылку на нужный тип сервиса; и когда объект создается, ссылка на реализацию нужного типа сервиса автоматически вставляется в это свойство (поле), используя средства среды.
Внедрение зависимости более гибко, потому что становится легче создавать альтернативные реализации данного типа сервиса, а потом указывать, какая именно реализация должна быть использована в, например, конфигурационном файле, без изменений в объектах, которые этот сервис используют. Это особенно полезно в юнит-тестировании, потому что вставить реализацию «заглушки» сервиса в тестируемый объект очень просто.
С другой стороны, излишнее использование внедрения зависимостей может сделать приложения более сложными и трудными в сопровождении: так как для понимания поведения программы программисту необходимо смотреть не только в исходный код, а еще и в конфигурацию, а конфигурация, как правило, невидима для IDE, которые поддерживают анализ ссылок и рефакторинг, если явно не указана поддержка фреймворков с внедрениями зависимостей.
Примеры кода
При использовании внедрения зависимостей, как правило, существует конфигурационный механизм или архитектура, которая определяет целесообразность выбора той или иной реализации в зависимости от поставленных целей.
Пример кода на Java
public interface ICar {
public float getSpeed();
public void setPedalPressure(final float PEDAL_PRESSURE);
}
public interface IEngine {
public float getEngineRotation();
public void setFuelConsumptionRate(final float FUEL_FLOW);
}
Без использования dependency injection
public class DefaultEngineImpl implements IEngine {
private float engineRotation = 0;
public float getEngineRotation() {
return engineRotation;
}
public void setFuelConsumptionRate(final float FUEL_FLOW) {
engineRotation = …;
}
}
public class DefaultCarImpl implements ICar {
private IEngine engine = new DefaultEngineImpl();
public float getSpeed() {
return engine.getEngineRotation()*…;
}
public void setPedalPressure(final float PEDAL_PRESSURE) {
engine.setFuelConsumptionRate(…);
}
}
public class MyApplication {
public static void main(String[] args) {
ICar car = new DefaultCarImpl();
car.setPedalPressure(5);
float speed = car.getSpeed();
System.out.println("Speed of the car is " + speed);
}
}
Внедрение зависимости вручную
public class DefaultCarImpl implements ICar {
private IEngine engine;
public DefaultCarImpl(final IEngine engineImpl) {
engine = engineImpl;
}
public float getSpeed() {
return engine.getEngineRotation()*…;
}
public void setPedalPressure(final float PEDAL_PRESSURE) {
engine.setFuelConsumptionRate(…);
}
}
public class CarFactory {
public static ICar buildCar() {
return new DefaultCarImpl(new DefaultEngineImpl());
}
}
public class MyApplication {
public static void main(String[] args) {
ICar car = CarFactory.buildCar();
car.setPedalPressure(5);
float speed = car.getSpeed();
System.out.println("Speed of the car is " + speed);
}
}
Внедрение зависимости при помощи фреймворка
<service-point id="CarBuilderService">
<invoke-factory>
<construct class="Car">
<service>DefaultCarImpl</service>
<service>DefaultEngineImpl</service>
</construct>
</invoke-factory>
</service-point>
/** Неявная реализация **/
public class MyApplication {
public static void main(String[] args) {
Service service = (Service)DependencyManager.get("CarBuilderService");
ICar car = (ICar)service.getService(Car.class);
car.setPedalPressure(5);
float speed = car.getSpeed();
System.out.println("Speed of the car is " + speed);
}
}
См. также
Напишите отзыв о статье "Внедрение зависимости"
Примечания
- ↑ 1 2 Martin, 2008.
Литература
- [www.manning.com/seemann/ Dependency Injection in .NET] — Mark Seemann, Manning, 2011
- [books.piter.com/product/vnedrenie-zavisimostey-v-net-3 Внедрение зависимостей в .NET] — Симан М., Питер, 2013.
- [smarly.net/dependency-injection-in-net Внедрение зависимостей в .NET] — Марк Симан, неофициальный перевод.
- Robert C. Martin. Clean Code: A Handbook of Agile Software Craftsmanship. — Pearson Education, 2008. — P. 157. — ISBN 978-0-13-608325-2.
Ссылки
- [www.martinfowler.com/articles/injection.html Inversion of Control Containers and the Dependency Injection pattern] — Martin Fowler.
- [www.ddj.com/185300375 Dependency Injection & Testable Objects: Designing loosely coupled and testable objects] — Jeremy Weiskotten; Dr. Dobb's Journal, May 2006.
- [msdn.microsoft.com/msdnmag/issues/05/09/DesignPatterns/default.aspx Design Patterns: Dependency Injection — MSDN Magazine, September 2005]
- [www.developer.com/net/net/article.php/3636501 Writing More Testable Code with Dependency Injection — Developer.com, October 2006]
- [www.pocomatic.com/docs/whitepapers/dsm Domain Specific Modeling (DSM) in IoC frameworks]
- [www.infoq.com/news/2007/12/does-di-pay-off Does Dependency Injection pay off? — InfoQ]
- [www.manning.com/prasanna Dependency Injection] — Dhanji R. Prasanna; Manning Publications, 2008.
<imagemap>: неверное или отсутствующее изображение |
Для улучшения этой статьи желательно?:
|
Отрывок, характеризующий Внедрение зависимости
– Задали, брат, жару. Теперь не сунутся, – говорил другой.– Ничего не видать. Как они в своих то зажарили! Не видать; темь, братцы. Нет ли напиться?
Французы последний раз были отбиты. И опять, в совершенном мраке, орудия Тушина, как рамой окруженные гудевшею пехотой, двинулись куда то вперед.
В темноте как будто текла невидимая, мрачная река, всё в одном направлении, гудя шопотом, говором и звуками копыт и колес. В общем гуле из за всех других звуков яснее всех были стоны и голоса раненых во мраке ночи. Их стоны, казалось, наполняли собой весь этот мрак, окружавший войска. Их стоны и мрак этой ночи – это было одно и то же. Через несколько времени в движущейся толпе произошло волнение. Кто то проехал со свитой на белой лошади и что то сказал, проезжая. Что сказал? Куда теперь? Стоять, что ль? Благодарил, что ли? – послышались жадные расспросы со всех сторон, и вся движущаяся масса стала напирать сама на себя (видно, передние остановились), и пронесся слух, что велено остановиться. Все остановились, как шли, на середине грязной дороги.
Засветились огни, и слышнее стал говор. Капитан Тушин, распорядившись по роте, послал одного из солдат отыскивать перевязочный пункт или лекаря для юнкера и сел у огня, разложенного на дороге солдатами. Ростов перетащился тоже к огню. Лихорадочная дрожь от боли, холода и сырости трясла всё его тело. Сон непреодолимо клонил его, но он не мог заснуть от мучительной боли в нывшей и не находившей положения руке. Он то закрывал глаза, то взглядывал на огонь, казавшийся ему горячо красным, то на сутуловатую слабую фигуру Тушина, по турецки сидевшего подле него. Большие добрые и умные глаза Тушина с сочувствием и состраданием устремлялись на него. Он видел, что Тушин всею душой хотел и ничем не мог помочь ему.
Со всех сторон слышны были шаги и говор проходивших, проезжавших и кругом размещавшейся пехоты. Звуки голосов, шагов и переставляемых в грязи лошадиных копыт, ближний и дальний треск дров сливались в один колеблющийся гул.
Теперь уже не текла, как прежде, во мраке невидимая река, а будто после бури укладывалось и трепетало мрачное море. Ростов бессмысленно смотрел и слушал, что происходило перед ним и вокруг него. Пехотный солдат подошел к костру, присел на корточки, всунул руки в огонь и отвернул лицо.
– Ничего, ваше благородие? – сказал он, вопросительно обращаясь к Тушину. – Вот отбился от роты, ваше благородие; сам не знаю, где. Беда!
Вместе с солдатом подошел к костру пехотный офицер с подвязанной щекой и, обращаясь к Тушину, просил приказать подвинуть крошечку орудия, чтобы провезти повозку. За ротным командиром набежали на костер два солдата. Они отчаянно ругались и дрались, выдергивая друг у друга какой то сапог.
– Как же, ты поднял! Ишь, ловок, – кричал один хриплым голосом.
Потом подошел худой, бледный солдат с шеей, обвязанной окровавленною подверткой, и сердитым голосом требовал воды у артиллеристов.
– Что ж, умирать, что ли, как собаке? – говорил он.
Тушин велел дать ему воды. Потом подбежал веселый солдат, прося огоньку в пехоту.
– Огоньку горяченького в пехоту! Счастливо оставаться, землячки, благодарим за огонек, мы назад с процентой отдадим, – говорил он, унося куда то в темноту краснеющуюся головешку.
За этим солдатом четыре солдата, неся что то тяжелое на шинели, прошли мимо костра. Один из них споткнулся.
– Ишь, черти, на дороге дрова положили, – проворчал он.
– Кончился, что ж его носить? – сказал один из них.
– Ну, вас!
И они скрылись во мраке с своею ношей.
– Что? болит? – спросил Тушин шопотом у Ростова.
– Болит.
– Ваше благородие, к генералу. Здесь в избе стоят, – сказал фейерверкер, подходя к Тушину.
– Сейчас, голубчик.
Тушин встал и, застегивая шинель и оправляясь, отошел от костра…
Недалеко от костра артиллеристов, в приготовленной для него избе, сидел князь Багратион за обедом, разговаривая с некоторыми начальниками частей, собравшимися у него. Тут был старичок с полузакрытыми глазами, жадно обгладывавший баранью кость, и двадцатидвухлетний безупречный генерал, раскрасневшийся от рюмки водки и обеда, и штаб офицер с именным перстнем, и Жерков, беспокойно оглядывавший всех, и князь Андрей, бледный, с поджатыми губами и лихорадочно блестящими глазами.
В избе стояло прислоненное в углу взятое французское знамя, и аудитор с наивным лицом щупал ткань знамени и, недоумевая, покачивал головой, может быть оттого, что его и в самом деле интересовал вид знамени, а может быть, и оттого, что ему тяжело было голодному смотреть на обед, за которым ему не достало прибора. В соседней избе находился взятый в плен драгунами французский полковник. Около него толпились, рассматривая его, наши офицеры. Князь Багратион благодарил отдельных начальников и расспрашивал о подробностях дела и о потерях. Полковой командир, представлявшийся под Браунау, докладывал князю, что, как только началось дело, он отступил из леса, собрал дроворубов и, пропустив их мимо себя, с двумя баталионами ударил в штыки и опрокинул французов.
– Как я увидал, ваше сиятельство, что первый батальон расстроен, я стал на дороге и думаю: «пропущу этих и встречу батальным огнем»; так и сделал.
Полковому командиру так хотелось сделать это, так он жалел, что не успел этого сделать, что ему казалось, что всё это точно было. Даже, может быть, и в самом деле было? Разве можно было разобрать в этой путанице, что было и чего не было?
– Причем должен заметить, ваше сиятельство, – продолжал он, вспоминая о разговоре Долохова с Кутузовым и о последнем свидании своем с разжалованным, – что рядовой, разжалованный Долохов, на моих глазах взял в плен французского офицера и особенно отличился.