0

我正在使用 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吧?)基本上是一种方法,表明已经建立了与数据库的新连接,并且获得相应的 SQLConnection实例。

编码:

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. 将导航器拆分为ConnectedStateNavigatorServiceand NotConnectedStateNavigator,这又需要将视图工厂拆分为ConnectedStateViewFactoryand NotConnectedStateViewFactory

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

我也不喜欢选项 2,因为这种带有侦听器、事件等的执行流程在我看来更适合 C#,而不是 Java 的正确选择。再一次,我不得不依靠额外的addListener电话。

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

我的问题是:你觉得这样好吗?

注意:我不想使用 mvvmFX 框架,因为我不喜欢所有的魔法并且也过于依赖反射。

(对不起我的英语,但我不是母语人士)

4

0 回答 0