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

Есть интерфейс
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 просмотров
Решения вопроса 1
@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, которая будет собирать все это в единое целое. Она самое конкретное что есть в нашей программе, так как она имеет дело с конкретными классами, экземпляры которых она создает. Поэтому она зависит от всех модулей - от модуля абстрактной логики и от модулей с реализациями интерфейсов. И тут принцип инверсии зависимостей тоже соблюдается - деталь (в какой именно конфигурации запускается программа) зависит от абстракции (абстрактная логики и конкретные реализации интерфейсов из которых выбирается именно та, которая будет использована)

Этот принцип очень хорошо объяснен в книге Р.Мартина "Чистая архитектура", по крайней мере у меня все встало на свои места именно после прочтения этой книги.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@Arlekcangp
Разработчик, Лид, Архитектор ПО
Посмотрите видео Александра Бындю по этой ссылке: https://blog.byndyu.ru/2013/06/blog-post_27.html (Это C# но в целом на Java очень похоже, поэтому должно восприниматься нормально) Он очень хорошо разворачивает там пример. После просмотра этого видео на код начинаешь смотреть по новому.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы