Инверсия шаблона управления, инъекции зависимостей и стратегии с примерами в java
меня часто путают эти три понятия. Эти трое похожи на меня. Может кто-нибудь, пожалуйста, объясните мне их четко, с примерами.
Я видел подобные посты и не понимаю.
3 ответов
Инъекции Зависимостей относится к шаблону говорить классу, что его зависимости будут, а не требовать, чтобы класс знал, где найти все его зависимости.
Итак, например, вы идете от этого:
public class UserFetcher {
private final DbConnection conn =
new DbConnection("10.167.1.25", "username", "password");
public List<User> getUsers() {
return conn.fetch(...);
}
}
Для что-то вроде этого:
public class UserFetcher {
private final DbConnection conn;
public UserFetcher(DbConnection conn) {
this.conn = conn;
}
public List<User> getUsers() {
return conn.fetch(...);
}
}
это уменьшает соединение в коде, что особенно полезно, если вы хотите модульный тест UserFetcher
. Теперь, вместо UserFetcher
всегда запуск против базы данных, найденной в 10.167.1.25
, вы можете пройти в DbConnection
в тестовую базу данных. Или, что еще более полезно в быстром тесте, вы можете пройти в реализации или подклассе DbConnection
это даже не подключиться к базе данных, он просто отбрасывает запросы!
однако такая примитивная инъекция зависимостей делает проводки (предоставление объекта с его зависимостями) сложнее, потому что вы заменили доступ к зависимости с помощью глобальной переменной (или локально инстанцированный объект) с передачей зависимости через весь граф объектов.
подумайте о случае, когда UserFetcher
зависимость AccountManager
, который является зависимостью AdminConsole
. Тогда AdminConsole
нужно пройти DbConnection
экземпляр AccountManager
и AccountManager
нужно передать его UserFetcher
...даже если ни AdminConsole
, ни AccountManager
нужно использовать DbConnection
напрямую!
An инверсия управления контейнер (Весна, Guice и т. д.) стремится сделать инъекцию зависимостей легче путем автоматического подключения (предоставления) зависимостей. Для этого вы говорите своему контейнеру МОК после как предоставить объект (весной это называется бин) и всякий раз, когда другой объект запрашивает эту зависимость, он будет предоставлен контейнером.
Итак, наш последний пример может выглядеть так с Guice, если использовать инъекцию конструктора.
public class UserFetcher {
private final DbConnection conn;
@Inject //or @Autowired for Spring
public UserFetcher(DbConnection conn) {
this.conn = conn;
}
public List<User> getUsers() {
return conn.fetch(...);
}
}
и мы должны настроить контейнер IoC. В Guice это делается через реализацию Module
; весной вы настраиваете контекст приложения, часто через XML.
public class MyGuiceModule extends AbstractModule {
@Override
public void configure() {
bind(DbConnection.class).toInstance(
new DbConnection("localhost", "username", "password"));
}
}
теперь, когда UserFetcher
построено Guice или весной,DbConnection
предоставляется автоматически.
Guice и действительно хорошая статья Wiki о мотивации инъекции зависимостей и дальнейшем использовании контейнера IoC. Это стоит прочитать всю дорогу. через.
на шаблон стратегии это просто частный случай инъекции зависимостей, где вы вводите логика вместо объект (хотя в Java логика будет инкапсулирована в объект). Это способ разделения независимой бизнес-логики.
например, у вас может быть такой код:
public Currency computeTotal(List<Product> products) {
Currency beforeTax = computeBeforeTax(products);
Currency afterTax = beforeTax.times(1.10);
}
но что, если вы хотите расширить этот код в новую юрисдикцию, с другой продажи налоговая схема? Вы можете ввести логику для вычисления налога, например:
public interface TaxScheme {
public Currency applyTax(Currency beforeTax);
}
public class TenPercentTax implements TaxScheme {
public Currency applyTax(Currency beforeTax) {
return beforeTax.times(1.10);
}
}
public Currency computeTotal(List<Product> products, TaxScheme taxScheme) {
Currency beforeTax = computeBeforeTax(products);
Currency afterTax = taxScheme.applyTax(beforeTax);
return afterTax;
}
инверсия управления означает, что среда выполнения связывает все компоненты вместе (например, Spring). Инъекция зависимостей-это форма МОК (я не знаю, существует ли другая форма МОК) (см.:http://en.wikipedia.org/wiki/Inversion_of_control).
шаблон стратегии-это шаблон дизайна (определенный GoF) , где алгоритм может быть заменен другим (см.:http://en.wikipedia.org/wiki/Strategy_pattern). Это архивируется предоставленным несколько реализаций одного интерфейса. При использовании IoC, как Spring, если у вас есть несколько реализаций интерфейса, и если вы можете переключиться с реализации на другую по конфигурации, вы используете шаблон стратегии.
Я также рекомендую прочитать главу введения документации Spring, которая посвящена этому вопросу: введение в Spring Framework
Достаточно первых нескольких абзацев.
и это также ссылки на: инверсия контейнеров управления и шаблон инъекции зависимостей
Что также дает мотивационный взгляд на эти очень важные основные концепции.