Циклическая зависимость заставляет меня разделять сервис и фабрику в зависимости от состояния.Это нормально? - PullRequest
0 голосов
/ 12 июля 2019

Я создаю настольное приложение JavaFX с использованием шаблона MVVM. Каждый View требует ViewModel. Вместо использования ViewA viewA = new ViewA(new ViewModelA()); я решил абстрагировать его, используя фабричный шаблон.

Конструктор ViewFactory имеет аргументы для других служб, которые нужны моделям представления. Например, часть моего приложения показывает все коллекции изображений, хранящиеся в базе данных, соответствующие CollectionsView и CollectionsViewModel. Чтобы извлечь все изображения и коллекции из базы данных, я создал CollectionService, который передается в ViewFactory.

код:

public interface CollectionService {
    List<ImageCollectionItem> getAllImagesForCollection(Collection collection);
    List<Collection> getAllCollections();
}

public class CollectionsView extends View<CollectionsViewModel> {
    public CollectionsView(CollectionsViewModel model) { ... }
}

public class CollectionsViewModel implements ViewModel {
    public CollectionsViewModel(CollectionService collectionService) {
        collections.set(collectionService.getAllCollections());
    }
}

public class ViewFactory {
    public ViewFactory(CollectionService collectionService) { ... }

    public CollectionsView createCollectionsView() {
        return new CollectionsView(new CollectionsViewModel(collectionService));
    }
}

Пока все отлично. Проблема начинается с другого View, ConnectView, который в основном представляет собой экран выбора базы данных с кнопкой подключения внизу. Когда кнопка подключения нажата, вид должен измениться на основной, скажем, CollectionsView для простоты.

Чтобы немного абстрагироваться, я создал интерфейс ConnectionManager (я знаю, что имя не самое лучшее, но я не мог придумать лучшего) новое подключение к базе данных установлено и передано соответствующий экземпляр SQL Connection.

код:

public class ConnectView { ... }

public class ConnectViewModel {
    public ConnectViewModel(ConnectionManager connectionManager, ...)

    public onConnectPress() {
        // check database exists, valid schema, etc
        // create connection
        connectionManager.connected(newConnection);
    }
}

public interface ConnectionManager {
    void connected(Connection connection);
}

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

Для этого я создал новый класс с именем NavigationService, который создает представление с использованием ViewFactory и устанавливает его как тот, что на экране.

код:

public class NavigationService {
    public NavigationService(ViewFactory viewFactory, ...) { ... }

    public void goToCollectionsView() {
        CollectionsView colView = viewFactory.createCollectionsView();
        // set colView on screen
    }
}

ConnectionManager connectionManagerImpl = connection -> {
    // create services that need connection (CollectionService, ...)
    navigator.goToCollectionsView();
}

Опять все работает хорошо. Но что, если у меня есть дополнительный View, который не требует подключенного состояния? Может быть, кнопка помощи на экране подключения, которая должна создать HelpView? Как вернуться на экран подключения? Чтобы добавить goToConnectView() в навигатор, я должен передать ему ConnectionManager, чтобы создать представление, которое, в свою очередь, требует навигатор.

Итак, чтобы создать ConnectionManager, мне нужен NavigatorService и наоборот.

Решения, о которых я думал:

  1. Создайте менеджер соединений без навигатора, создайте навигатор, а затем просто используйте установщик.
  2. Создайте менеджер соединений без навигатора, создайте навигатор и используйте шаблон слушателя для вызова навигатора при установлении нового соединения.
  3. Разделите навигатор на ConnectedStateNavigatorService и NotConnectedStateNavigator, что, в свою очередь, требует разделения фабрики просмотра на ConnectedStateViewFactory и NotConnectedStateViewFactory.

Мне не нравится вариант 1, потому что я не хочу зависеть от дополнительного утверждения, просто кажется грязным.

Мне тоже не нравится вариант 2, потому что такой вид выполнения со слушателями, событиями и т. Д. Кажется мне более подходящим для C #, а не для правильного выбора для Java. И снова, я должен положиться на дополнительный addListener звонок.

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

Мой вопрос: как вы думаете, это нормально?

Примечание: я не хочу использовать фреймворк mvvmFX, потому что мне не нравится вся магия, а также слишком много полагаюсь на рефлексию.

(извините за мой английский, но я не являюсь носителем языка)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...