Внедрение зависимости — Википедия

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

[ править | править вики-текст]
Материал из Википедии — свободной энциклопедии

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

## Принцип работы[ править | править вики-текст]

| В этом разделе не хватает ссылок на источники информации. Информация должна быть проверяема, иначе она может быть поставлена под сомнение и удалена. Вы можете отредактировать эту статью, добавив ссылки на авторитетные источники. Эта отметка установлена 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();
        }
    }

## См. также[ править | править вики-текст]

- Замыкание (программирование)
- Стратегия (шаблон проектирования)

## Литература[ править | править вики-текст]

- Dependency Injection in .NET — Mark Seemann, Manning, 2011
- Внедрение зависимостей в .NET — Симан М., Питер, 2013.
- Внедрение зависимостей в .NET — Марк Симан, неофициальный перевод.

## Ссылки[ править | править вики-текст]

- Inversion of Control Containers and the Dependency Injection pattern — Martin Fowler.
- Dependency Injection & Testable Objects: Designing loosely coupled and testable objects — Jeremy Weiskotten; Dr. Dobb's Journal, May 2006.
- Design Patterns: Dependency Injection — MSDN Magazine, September 2005
- Writing More Testable Code with Dependency Injection — Developer.com, October 2006
- Domain Specific Modeling (DSM) in IoC frameworks
- Does Dependency Injection pay off? — InfoQ
- Dependency Injection — Dhanji R. Prasanna; Manning Publications, 2008.

Для улучшения этой статьи желательно?:

- Проставив сноски, внести более точные указания на источники.

Источник — «http://ru.wikipedia.org/w/index.php?title=Внедрение_зависимости&oldid=65795902»
Категории:

- Шаблоны проектирования
- Архитектура программного обеспечения

Скрытые категории:

- Википедия:Статьи с разделами без ссылок на источники с ноября 2013 года
- Википедия:Статьи без сносок
- Статьи с примерами кода Python