Слабая связь между слоями приложения MVC
Делаю учебное задание - консольное приложение, реализующее MVC и Repository
.controller - обработка действий пользователя
.action - действия пунктов меню
.model - бизнес-логика приложения
.entity - сущности приложения
.repository - подпакеты с интерфейсами и классами-хранилищами
.service - бизнес-логика приложения
.view - отображение данных пользователю
Создал интерфейс, который обобщает все задачи бизнес-логики и имплементировал его классу-фасаду. Хранилища и класс-фасад - Singleton, доступ к ним по getInstance.
При работе в action мне необходимо вызвать методы фасада.
IFasad fasad = Fasad.getInstance();
Преподаватель говорит, что в таком случае у меня пропадает слабая связь и контроллер знает реализацию фасада.
Аналогичная ситуация с репозиториями и сервисами сущностей.
IEntityReposytori reposytori = EntityReposytory.getInstance();
Подскажите правильный вариант реализации взаимодействия между слоями.
Ответы (1 шт):
Что значит слабая связь? Это когда один объект не знает ничего о другом объекте, только об интерфейсе.
Сильная связь
К примеру вы можете написать такой код:
ArrayList<String> strings = new ArrayList<>(); strings.add("Hello");Вы создали конкретный класс
ArrayListи теперь ваш класс знает о конкретной реализацииArrayList. Чем это чревато? К примеру завтра вы решили что вам больше не подходитArrayList, а нуженLinkedList. Вам придется идти и менять код наLinkedList<String> anotherStrings = new LinkedList<>(); anotherStrings.add("Hello");Казалось бы ничего страшного, поменяли 1 строку. Теперь представим что вы передаете этот
ArrayListеще в 5-10 других методов как параметр и везде вы в функции указываетеArrayListкак аргумент функции:public void soneMethod(ArrayList<String> list){ // some code }Так вот когда вы захотите использовать
LinkedListвам придется поменять его во всех функциях в которых есть вашArrayList.Слабая связь
List<String> anotherStrings = new ArrayList<>(); anotherStrings.add("Hello");И пример ваших функций который принимают на вход ваш список
public void soneMethod(List<String> list){ // some code }Если завтра вам понадобится
LinkedListто вам придется поменять только 1 строку кода и все остальное работает.List<String> anotherStrings = new LinkedList<>();Почему? Потому что весь ваш код зависит от только от интерфейса
List. А это значит, что вашему коду все равно что вы там напишете лишь бы оно реализовывало интерфейсList:ArrayDeque<E>,ReversedList<T>и т.д.А еще в более серьезных проектах используется DI (Внедрение зависимостей) где то как будет создаваться объект указано только в одном месте, а значит что если ваш код использует какую-то зависимость только от интерфейса и вам вдруг надо подменить один объект на другой, то вы меняете это в одном месте и весь проект продолжает работать.
Что еще не хватает вам? Объекты одного класса не должны создаваться внутри другого класса (но без фанатизма, какие-то вещи все же создаются внутри класса).
Возьмем ваш случай. У вас условно есть
class Controllerclass Controller { IEntityReposytori reposytori = EntityReposytory.getInstance(); // some code }Внутри вашего контроллера вы создаете явный экземпляр
EntityReposytory, а значит, что вашControllerзависит отEntityReposytory, вы не сможете подменить его в тестах или динамически при создании контроллера т.к. это внутрення реализация классаController.Что можно сделать? Можно передавать
IEntityReposytoriв конструкторе, например так:class Controller { IEntityReposytori reposytori; Controller (IEntityReposytori reposytori){ this.reposytori = reposytori; } // some code }Что нам это даст? Так вы можете подменять объект вашего репозитория в рантайме динамически. Пример:
public static void main(String[] args) { Controller controller; if (debug){ controller = Controller(DebugRepository.getInstance()); } else { controller = Controller(ProductionRepository.getInstance()); } }Внутри класс будет работать независимо от того, что вы ему передадите, главное чтоб это "что-то" реализовало интерфейс
IEntityReposytori.
Почитайте эту статью. Там неплохо объясняется, что такое "Внедрение зависимостей".
Так же рекомендую почитать серию статей про Dagger. Вы можете не читать все, если слово Dagger для вас звучит, как что-то дикое, но вот первые 3 прочесть стоит, там общие понятия и примеры: