循环依赖性迫使我根据状态拆分服务和工厂。还行吗?

时间:2019-07-12 02:44:45

标签: java javafx software-design cyclic-reference cyclic-dependency

我正在使用MVVM模式创建JavaFX桌面应用程序。每个View需要一个ViewModel。我决定不使用ViewA viewA = new ViewA(new ViewModelA());,而是使用工厂模式对其进行抽象。

ViewFactory构造函数具有用于视图模型所需的其他服务的参数。例如,我的应用程序的一部分正在显示与CollectionsViewCollectionsViewModel相对应的数据库中存储的所有图像集合。为了从数据库中检索所有图像和集合,我创建了一个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接口(我知道名称不是最好的接口,但我想不出更好的接口。也许ConnectionNotifier?)表示已建立与数据库的新连接,并已通过相应的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. ConnectedStateNavigatorServiceNotConnectedStateNavigator中拆分导航器,这又需要在ConnectedStateViewFactoryNotConnectedStateViewFactory中拆分视图工厂。

我不喜欢选项1,因为我不想依赖额外的语句,看起来很脏。

我也不喜欢选项2,因为在我看来,这种带有侦听器,事件等的执行流程更适合C#,而不是Java的正确选择。同样,我必须依靠额外的addListener调用。

虽然我不喜欢选项3,但这是我的选择。但同样,它感觉不对。我的代码开始变得杂乱无章,服务,工厂在我的应用程序中已将它们编码为接口,这意味着每个工厂都需要额外的类。

我的问题是:您认为可以吗?

注意:我不想使用mvvmFX框架,因为我不喜欢所有魔术,也不太依赖反射。

(抱歉我的英语,但我不是母语人士)

0 个答案:

没有答案