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

Поделись знанием:
Перейти к: навигация, поиск

Внедрение зависимости (англ. Dependency injection, DI) — процесс предоставления внешней зависимости программному компоненту. Является специфичной формой «инверсии управления» (англ. Inversion of control, IoC), когда она применяется к управлению зависимостями. В полном соответствии с принципом единой обязанности объект отдаёт заботу о построении требуемых ему зависимостей внешнему, специально предназначенному для этого общему механизму[1].

JNDI-запросы сервиса, когда объект запрашивает сервис по имени, реализуют внедрение зависимости лишь частично.





Настоящее внедрение зависимости

При настоящем внедрении зависимости объект пассивен и не предпринимает вообще никаких шагов для выяснения зависимостей, а предоставляет для этого сеттеры и/или принимает своим конструктором аргументы, посредством которых внедряются зависимости[1].

Принцип работы

К:Википедия:Статьи без источников (тип: не указан)

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

См. также

Напишите отзыв о статье "Внедрение зависимости"

Примечания

Литература

  • [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.


Отрывок, характеризующий Внедрение зависимости

– Задали, брат, жару. Теперь не сунутся, – говорил другой.
– Ничего не видать. Как они в своих то зажарили! Не видать; темь, братцы. Нет ли напиться?
Французы последний раз были отбиты. И опять, в совершенном мраке, орудия Тушина, как рамой окруженные гудевшею пехотой, двинулись куда то вперед.
В темноте как будто текла невидимая, мрачная река, всё в одном направлении, гудя шопотом, говором и звуками копыт и колес. В общем гуле из за всех других звуков яснее всех были стоны и голоса раненых во мраке ночи. Их стоны, казалось, наполняли собой весь этот мрак, окружавший войска. Их стоны и мрак этой ночи – это было одно и то же. Через несколько времени в движущейся толпе произошло волнение. Кто то проехал со свитой на белой лошади и что то сказал, проезжая. Что сказал? Куда теперь? Стоять, что ль? Благодарил, что ли? – послышались жадные расспросы со всех сторон, и вся движущаяся масса стала напирать сама на себя (видно, передние остановились), и пронесся слух, что велено остановиться. Все остановились, как шли, на середине грязной дороги.
Засветились огни, и слышнее стал говор. Капитан Тушин, распорядившись по роте, послал одного из солдат отыскивать перевязочный пункт или лекаря для юнкера и сел у огня, разложенного на дороге солдатами. Ростов перетащился тоже к огню. Лихорадочная дрожь от боли, холода и сырости трясла всё его тело. Сон непреодолимо клонил его, но он не мог заснуть от мучительной боли в нывшей и не находившей положения руке. Он то закрывал глаза, то взглядывал на огонь, казавшийся ему горячо красным, то на сутуловатую слабую фигуру Тушина, по турецки сидевшего подле него. Большие добрые и умные глаза Тушина с сочувствием и состраданием устремлялись на него. Он видел, что Тушин всею душой хотел и ничем не мог помочь ему.
Со всех сторон слышны были шаги и говор проходивших, проезжавших и кругом размещавшейся пехоты. Звуки голосов, шагов и переставляемых в грязи лошадиных копыт, ближний и дальний треск дров сливались в один колеблющийся гул.
Теперь уже не текла, как прежде, во мраке невидимая река, а будто после бури укладывалось и трепетало мрачное море. Ростов бессмысленно смотрел и слушал, что происходило перед ним и вокруг него. Пехотный солдат подошел к костру, присел на корточки, всунул руки в огонь и отвернул лицо.
– Ничего, ваше благородие? – сказал он, вопросительно обращаясь к Тушину. – Вот отбился от роты, ваше благородие; сам не знаю, где. Беда!
Вместе с солдатом подошел к костру пехотный офицер с подвязанной щекой и, обращаясь к Тушину, просил приказать подвинуть крошечку орудия, чтобы провезти повозку. За ротным командиром набежали на костер два солдата. Они отчаянно ругались и дрались, выдергивая друг у друга какой то сапог.
– Как же, ты поднял! Ишь, ловок, – кричал один хриплым голосом.
Потом подошел худой, бледный солдат с шеей, обвязанной окровавленною подверткой, и сердитым голосом требовал воды у артиллеристов.
– Что ж, умирать, что ли, как собаке? – говорил он.
Тушин велел дать ему воды. Потом подбежал веселый солдат, прося огоньку в пехоту.
– Огоньку горяченького в пехоту! Счастливо оставаться, землячки, благодарим за огонек, мы назад с процентой отдадим, – говорил он, унося куда то в темноту краснеющуюся головешку.
За этим солдатом четыре солдата, неся что то тяжелое на шинели, прошли мимо костра. Один из них споткнулся.
– Ишь, черти, на дороге дрова положили, – проворчал он.
– Кончился, что ж его носить? – сказал один из них.
– Ну, вас!
И они скрылись во мраке с своею ношей.
– Что? болит? – спросил Тушин шопотом у Ростова.
– Болит.
– Ваше благородие, к генералу. Здесь в избе стоят, – сказал фейерверкер, подходя к Тушину.
– Сейчас, голубчик.
Тушин встал и, застегивая шинель и оправляясь, отошел от костра…
Недалеко от костра артиллеристов, в приготовленной для него избе, сидел князь Багратион за обедом, разговаривая с некоторыми начальниками частей, собравшимися у него. Тут был старичок с полузакрытыми глазами, жадно обгладывавший баранью кость, и двадцатидвухлетний безупречный генерал, раскрасневшийся от рюмки водки и обеда, и штаб офицер с именным перстнем, и Жерков, беспокойно оглядывавший всех, и князь Андрей, бледный, с поджатыми губами и лихорадочно блестящими глазами.
В избе стояло прислоненное в углу взятое французское знамя, и аудитор с наивным лицом щупал ткань знамени и, недоумевая, покачивал головой, может быть оттого, что его и в самом деле интересовал вид знамени, а может быть, и оттого, что ему тяжело было голодному смотреть на обед, за которым ему не достало прибора. В соседней избе находился взятый в плен драгунами французский полковник. Около него толпились, рассматривая его, наши офицеры. Князь Багратион благодарил отдельных начальников и расспрашивал о подробностях дела и о потерях. Полковой командир, представлявшийся под Браунау, докладывал князю, что, как только началось дело, он отступил из леса, собрал дроворубов и, пропустив их мимо себя, с двумя баталионами ударил в штыки и опрокинул французов.
– Как я увидал, ваше сиятельство, что первый батальон расстроен, я стал на дороге и думаю: «пропущу этих и встречу батальным огнем»; так и сделал.
Полковому командиру так хотелось сделать это, так он жалел, что не успел этого сделать, что ему казалось, что всё это точно было. Даже, может быть, и в самом деле было? Разве можно было разобрать в этой путанице, что было и чего не было?
– Причем должен заметить, ваше сиятельство, – продолжал он, вспоминая о разговоре Долохова с Кутузовым и о последнем свидании своем с разжалованным, – что рядовой, разжалованный Долохов, на моих глазах взял в плен французского офицера и особенно отличился.