Инверсия зависимости на примере

139
08 февраля 2022, 22:50

В книге "Чистый код" всё время говорится про то, что инверсия зависимостей - это замечательная вещь. Наверно, эта правда ввиду профессионализма и опыта автора, но я так и понял, как это можно "ссылаться только на абстракции, не указывая конкретных их реализаций".

Представлю свой ход мыслей, как я пытался это понять, начав с жестко связанного кода. В приведённом ниже Java-коде (окружение методом опущено) Realization - одна из реализаций ISomeInterface:

ISomeInterface example = new Realization();

Здесь переменная переменная имеет тип ISomeInterface, но класс Realization-то мы должны в явном виде импортировать в файл!

Далее, я знаю, что фреймворк Spring даёт нам контекст, из которого можно получить конкретные экземпляры классов (внедрение зависимостей). Уже лучше, чем пример выше, но имя бина-то мы в Java-коде указать всё равно должны! Получается, что тут ссылка на конкретную реализацию есть, но нет прямого импорта класса в файл.

Ну и плюс не понятно, что делать, когда нет фреймворка типа Spring (тем более что на данный момент мой основной язык - TypeScript). Так что в этом вопросе я прошу показать пример, как это так можно ссылаться на абстракции не импортируя в модуль её реализацию.

  • С Ответами на вопрос Разница между инверсией управления и внедрением зависимостей ознакомился;
  • Если минусуете вопрос - пишите за что, чтобы я Вас в будущем не раздражал правильно заданными (в соответствие со своими представлениями) вопросами
Answer 1

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

 public interface PersonService{
    ...
    Person getPerson(Long id);
    ...
 }

Все остальные классы ничего не знают о реализации данного метода. Они у себя внутри используют только метод getPersons(Long id). Соответственно они ничего не знают о реализации данного метода кроме того, что они должны передать ему на вход и что он возвращает. Вы не должны в других классах использовать специфические методы реализации, вы используете только те методы, которые есть в интерфейсе.

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

Например

public class PersonControllerImpl{
    private PersonService service;
    PersonControllerImpl(PersonService service){
        this.service = service;
    }
    Person getPerson(Long id){
        service.getPerson(id); 
    }
} 

Ваш контроллер ничего не знает о реализации сервиса. Конечно будет какой-то метод, который сделает new PersonServiceImpl() и передаст его на вход в контроллер, но сам контроллер от реализации никак не зависит. Например:

class PersonsContainer{
    private PersonService personService;
    private PersonController personController;
    PersonsContainer(){
        personService = new PersonServiceImpl();
        personController = new PersonControllerImpl( personService );
    }
}

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

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

Что это дает:

  • чтоб при изменении одного класса не приходилось по цепочке менять половину программы;
  • возможность повторного применения классов в других проектах.
READ ALSO
php > 7.0 устарел mbstring

php > 7.0 устарел mbstring

mbstring же устарел в 7х версиях пхптак почему же функции mb_ продолжают работать, без deprecated?

90
Исключить из кеширования

Исключить из кеширования

помогите, пожалуйста, исключить из кеширования следующий код (одна из функций в файле techmarket-woocommerce-template-functionsphp):

92
Как вернуть значение базы данных meta_value в Wordpress

Как вернуть значение базы данных meta_value в Wordpress

Есть wordpress фреймворк Unyson, работает на bootstrapПоддерживает расширения и кастомные опции

97