Принцип инверсии зависимостей внутри

Я читал о твердых принципах ООП (Принцип инверсии зависимостей) и не совсем понял, как это работает.

Когда один класс явно знает о конструкции и реализации другого класса, изменения в одном классе повышают риск нарушения работы другого класса.

скажем, у меня есть студент, который зависит от курса, если я изменю курс, как это повлияет на студента. То же самое - использовать DI. Я имею в виду, что DI заменяет новый оператор, и что тогда? студент по-прежнему зависит от курса
вы можете привести несколько примеров, пожалуйста.
спасибо

public class Student {
.....
private Course course = new Course(); 
}

обновлено 1

(сценарий), если я предполагаю, что у класса есть только конструктор по умолчанию, и он никогда не будет использовать какие-либо переменные экземпляра для создания экземпляра, например new Course(name, .......)

обновлено 2

Пример

public class Copy {
    @Autowired
    private Writer writer;
.....
}

public interface Writer{
    void write();
}


public class PrinterWriter implements Writer {
.....
}

public class DiskWriter implements Writer {
....
}

Теперь происходит то, что нашему модулю копирования нужно знать о принтере и диске. Вы можете представить себе те волшебные операторы if-else, которые приходят нам на помощь в таких ситуациях. По мере появления новых требований вы, вероятно, добавляете все больше и больше зависимостей в этот модуль копирования. В конце концов, вы получите очень сложный, трудный в обслуживании и трудный для понимания дизайн.

Можете ли вы показать в этом примере, где именно инверсия зависимостей исключает использование волшебных операторов if-else с простым примером, пожалуйста


person M.T    schedule 25.12.2016    source источник
comment
Попробуйте этот lostechies.com/gabrielschenker/2009/01/30 /   -  person Patrick Parker    schedule 25.12.2016
comment
Возможный дубликат Что такое принцип инверсии зависимостей и почему это важно?   -  person Patrick Parker    schedule 25.12.2016
comment
Это вопрос о конкретной проблеме моделирования зависимостей или о том, к чему вы идете? Студент никогда не должен зависеть от курса в реальной системе, поскольку студент записывается не на один курс, а на множество ...   -  person Florian Salihovic    schedule 25.12.2016
comment
@FlorianSalihovic это был простой пример для понимания принципа инверсии зависимостей   -  person M.T    schedule 26.12.2016


Ответы (3)


Возьмем сценарий, в котором совершенно очевидно, что Course должен изменить конструктор. Допустим, добавляется новый параметр, а в классе Course нет конструктора по умолчанию.

public class Course{
  public Course(String name){}
}

Теперь у класса Student будет ошибка компилятора.

public class Student {
   private Course course = new Course(); //ERROR !! no such constructor exist 
}

С помощью DI класс Student может быть реализован с помощью конструктора следующим образом:

public class Student {
   private Course course;
   public Student(Course course){
      this.course=course;
   }
}

Итак, здесь, независимо от изменений в Course, класс Student не поврежден. То же самое можно сделать с помощью мутаторов свойств или методов получения-установки поля.

Отредактировано. Есть несколько других случаев, когда ваш Student класс потребует изменений. Требование для введения новых Course типов Optional и Mandatory или Prerequisite. Создание экземпляра Course со значениями из базы данных или другого источника данных. Рефакторинг кода с помощью таких инструментов, как IDE.

person Community    schedule 25.12.2016
comment
что, если конструктор никогда не меняется, есть ли еще что-нибудь? - person M.T; 25.12.2016

Пролог

Принцип инверсии зависимостей (DIP) был впервые представлен в одной из статей Боба Мартина в отчете на C ++. В этой статье он перечислил пять следующих принципов как Принципы объектно-ориентированного проектирования, также известные как принципы SOLID:

  1. Принцип единой ответственности (SRP)
  2. Принцип открытости и закрытости (OCP)
  3. Принцип замещения Лискова (LSP)
  4. Принцип разделения интерфейса (ISP)
  5. Принцип инверсии зависимостей (DIP)

Вы можете узнать больше об этих принципах в статье Принципы OOD.

Определение

Формальное определение, которое дядя Боб дал в статье, было:

Модули высокого уровня не должны зависеть от модулей низкого уровня. Оба должны зависеть от абстракций.

Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

Пример

Одним из примеров, которые дядя Боб привел в своей статье, была Программа копирования, которая читает с клавиатуры и пишет на принтер:

введите описание изображения здесь

Здесь модуль копирования зависит от двух других модулей, что пока кажется очень разумным дизайном. Фактически, эти два использованных модуля прекрасно подходят для повторного использования. Любая другая абстракция, которая должна читать с клавиатуры или писать на принтер, могла бы повторно использовать предоставленные им функции.

Однако модуль копирования нельзя повторно использовать в любом контексте, который не связан с клавиатурой или принтером (кстати, они очень зависят от реализации). Например, предположим, что вместо того, чтобы просто писать на принтер, нам иногда также нужно писать на диск:

введите описание изображения здесь

Теперь происходит то, что нашему модулю копирования нужно знать о принтере и диске. Вы можете представить себе те волшебные if-else утверждения, которые приходят нам на помощь в таких ситуациях. По мере появления новых требований вы, вероятно, добавляете все больше и больше зависимостей в этот модуль копирования. В конце концов, вы получите очень сложный, трудный в обслуживании и трудный для понимания дизайн.

Итак, что было не так с нашим плохим модулем копирования? Проблема заключалась не в зависимости от абстракций, а от конкретных реализаций читателей и писателей. Чтобы решить эту проблему, модуль копирования должен зависеть от абстрактных определений для Reader и Writer:

введите описание изображения здесь

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

Дополнительная информация

Исходная бумажная ссылка сейчас кажется неработающей, но вы можете узнать больше о DIP здесь

person Ali Dehghani    schedule 25.12.2016
comment
Я обновил вопрос, не могли бы вы помочь лучше понять его, спасибо - person M.T; 26.12.2016

Я бы добавил уровень косвенности: class Curriculum. Класс координирует участников курса и может быть единственной точкой перемен.

interface CourseSystem {

  enum Role { PROFESSOR, STUDENT, STAFF };

  /**
   * Abstraction over a course. It does not know
   */
  interface Course {
    boolean addParticipant(Participant participant)
  }

  interface Curriculum {
    boolean register(Participant participant);
  }

  interface Participant {
    default void setCurriculum(final Curriculum curriculum) {
      curriculum.register(this);
    }
  }
}

Отсюда вы можете реализовать конкретные классы Professor, Student или Staff, которые имеют выделенные привилегии и т. Д.

person Florian Salihovic    schedule 25.12.2016