WikiSort.ru - Не сортированное

ПОИСК ПО САЙТУ | о проекте

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

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

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

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

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

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

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

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

Примеры кода

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

Пример кода на PHP

 1 <?php
 2 /**
 3  * Класс конфигурация базы данных
 4  */
 5 class DbConfiguration{
 6     
 7     private $host;
 8     private $port;
 9     private $username;
10     private $password;
11 
12     public function __construct(string $host, int $port, string $username, string $password){
13         // вся соль Di находится в строчках ниже
14         $this->host = $host;
15         $this->port = $port;
16         $this->username = $username;
17         $this->password = $password;
18     }
19 
20     public function getHost(){
21         return $this->host;
22     }
23 
24     public function getPort(){
25         return $this->port;
26     }
27 
28     public function getUsername(){
29         return $this->username;
30     }
31 
32     public function getPassword(){
33         return $this->password;
34     }
35 }
36 
37 /**
38  * Класс соединение с базой данных
39  */
40 class DbConnection{
41 
42     private $configuration;
43 
44     public function __construct(DbConfiguration $config){
45         // вся соль Di находится в строчке ниже
46         $this->configuration = $config;
47     }
48 
49     public function getDsn(){
50         // примечание: это не реальный dsn, разделители в реальном dsn другие
51         return sprintf(
52             '%s:%s@%s:%d',
53             $this->configuration->getUsername(),
54             $this->configuration->getPassword(),
55             $this->configuration->getHost(),
56             $this->configuration->getPort()
57         );
58     }
59 }
60 
61 // создаем объект конфигурации базы данных, передав в конструктор параметры
62 $config = new DbConfiguration('localhost', 3306, 'username', 'password');
63 // создаем объект соединения с базой, передав в конструктор объект конфигурации
64 // использование Di дает слабосвязность кода
65 $connection = new DbConnection($config);

Пример кода на 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) {
        DefaultCarImpl 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);
    }
}

См. также

Примечания

Литература

Ссылки

Данная страница на сайте WikiSort.ru содержит текст со страницы сайта "Википедия".

Если Вы хотите её отредактировать, то можете сделать это на странице редактирования в Википедии.

Если сделанные Вами правки не будут кем-нибудь удалены, то через несколько дней они появятся на сайте WikiSort.ru .




Текст в блоке "Читать" взят с сайта "Википедия" и доступен по лицензии Creative Commons Attribution-ShareAlike; в отдельных случаях могут действовать дополнительные условия.

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

2019-2024
WikiSort.ru - проект по пересортировке и дополнению контента Википедии