Разница между созданием нового объекта и внедрением зависимости - PullRequest
18 голосов
/ 02 августа 2010

В чем разница между созданием нового объекта и внедрением зависимости? Пожалуйста, объясните подробно.

Ответы [ 5 ]

21 голосов
/ 02 августа 2010

Ну, они не совсем сопоставимы.Вам всегда придется создавать новый объект, создавая экземпляр класса в какой-то момент.Внедрение зависимостей также требует создания новых объектов.

Внедрение зависимостей действительно вступает в игру, когда вы хотите контролировать или проверять поведение экземпляров, используемых классом, который вы используете или хотите протестировать.(Для Test Driven Development внедрение зависимостей является ключевым для всех, кроме самого маленького примера.)

Предположим, что класс Holder требует объект класса Handle.Традиционный способ сделать это - позволить экземпляру Holder создать и владеть им:

class Holder {
    private Handle myHandle = new Handle();
    public void handleIt() {
        handle.handleIt();
    }
}

Экземпляр Holder создает myHandle, и никто за пределами класса не может получить к нему доступ.В некоторых случаях, когда модульное тестирование является одним из них, это проблема, потому что невозможно протестировать класс Holder без создания экземпляра Handle, который, в свою очередь, может зависеть от многих других классов и экземпляров.Это делает тестирование громоздким и громоздким.

Путем внедрения экземпляра Handle, например, в конструктор, кто-то извне становится ответственным за создание экземпляра.

class Holder {
    private Handle myHandle;

    public Holder(Handle injectedHandle) {
        myHandle = injectedHandle;
    }

    public void handleIt() {
        handle.handleIt();
    }
}

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

Фактическая инъекция будет иметь местов каком-то другом месте, обычно в какой-то «основной» программе.Существует множество фреймворков, которые могут помочь вам сделать это без программирования, но, по сути, это код «основной» программы:

...
private Handle myHandle = new Handle(); // Create the instance to inject
private Handler theHandler = new Handler(myHandle); // Inject the handle
...

По сути, внедрение - это не более чем причудливый set метод.,И, конечно, вы можете реализовать механизм внедрения, используя его вместо конструктора, как в простом примере выше.

16 голосов
/ 02 августа 2010

Что ж, создание нового объекта настолько явно, насколько это возможно - вы создаете новый экземпляр нужного класса.

Инъекции зависимостей - это механизм, который предоставляет вам ссылки там, где они вам нужны.Представьте себе класс, который представляет пул соединений с вашей базой данных - у вас обычно есть только один экземпляр этого класса.Теперь вам нужно распространить эту ссылку на все классы, которые ее используют.Вот где Dependency Injection пригодится - с помощью DI-фреймворка, такого как Spring, вы можете определить, что один экземпляр вашего пула будет внедрен в классы, которые в этом нуждаются.

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

16 голосов
/ 02 августа 2010

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

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

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

3 голосов
/ 02 августа 2010

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

2 голосов
/ 02 августа 2010

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

Я бы посоветовал вам прочитать несколько статей о внедрении зависимостей и / или Spring. Или прочитайте другие темы по внедрению зависимостей здесь, на SO.

...