Инверсия шаблона управления, инъекции зависимостей и стратегии с примерами в 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
Достаточно первых нескольких абзацев.

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