Задать вопрос

Правильно ли я понял принцип инверсии зависимостей?

Есть интерфейс
public interface INumberOperation {
    public void executeOperation (int number);
}


Этот интерфейс реализует несколько классов, которые выполняют различные операции.
public class NumberOperation1 implements INumberOperation{
    @Override
    public void executeOperation(int number) {
        number += number * 2;
        System.out.println(number);
    }
}

public class NumberOperation2 implements INumberOperation{
    @Override
    public void executeOperation(int number) {
        number += 100;
        System.out.println(number);
    }
}


И выполняется в главном классе.
public class Main  {
    public static void main(String[] args) {
        INumberOperation iNumberOperation;
        iNumberOperation = new NumberOperation1();
        iNumberOperation.executeOperation(100);
        iNumberOperation = new NumberOperation2();
        iNumberOperation.executeOperation(100);
    }
}


То есть, я не зависим от конкретного класса выполняющий определенную задачу.
Если я правильно понял реализацию инверсии зависимостей, то чем она отличается от паттерна стратегия?
  • Вопрос задан
  • 539 просмотров
Подписаться 5 Простой 1 комментарий
Решение пользователя Михаил К ответам на вопрос (2)
@Akela_wolf
Extreme Programmer
Главная идея принципа инверсии зависимостей "детали зависят от абстракций, но не абстракции от деталей".
В приведенном вами примере класс Main зависит от всего: от интерфейса INumberOperation и от обоих классов NumberOperation1, NumberOperation2. То есть тут принцип инверсии зависимостей вообще не работает. Никак.

Проявляется же он в следующем примере. Пусть у меня есть некая абстрактная логика "прочитай число, выполни над ним операцию, запиши результат". Эта абстрактная логика (потому она и абстрактная) ничего не должна знать ни откуда она читает число, ни какую операцию над ним выполняет, ни куда и как записывает результат. Таким образом, у нас есть модуль, состоящий из
interface NumberInput {
  int read();
}
interface NumberProcessor {
  int process(int a);
}
interface NumberOutput {
  void write(int a);
}
class Processor {
  private final NumberInput input;  
  private final NumberProcessor processor;
  private final NumberOutput output;

  public Processor(NumberInput input, NumberProcessor processor, NumberOutput output) {
    this.input = input;
    this.processor = processor;
    this.output = output;
  }

  void process() {
    output.write(processor.process(input.read()));
  }
}

Все. Модуль получился очень абстрактным и ни от кого никак не зависящим.
Затем мы можем сделать реализации этих интерфейсов - они будут зависеть от нашего модуля логики (так как ссылаются на интерфейсы). И это полностью соответствует принципу инверсии зависимостей - детали зависят от абстракций.

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

Этот принцип очень хорошо объяснен в книге Р.Мартина "Чистая архитектура", по крайней мере у меня все встало на свои места именно после прочтения этой книги.
Ответ написан