我正在使用 MVVM 模式创建 JavaFX 桌面应用程序。每个都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
接口(我知道这个名字不是最好的,但我想不出更好的名字。也许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
,反之亦然。
我想过的解决方案:
- 创建没有导航器的连接管理器,创建导航器,然后只使用设置器。
- 创建没有导航器的连接管理器,创建导航器并在建立新连接时使用侦听器模式调用导航器。
- 将导航器拆分为
ConnectedStateNavigatorService
andNotConnectedStateNavigator
,这又需要将视图工厂拆分为ConnectedStateViewFactory
andNotConnectedStateViewFactory
。
我不喜欢选项 1,因为我不想依赖额外的语句,只是看起来很脏。
我也不喜欢选项 2,因为这种带有侦听器、事件等的执行流程在我看来更适合 C#,而不是 Java 的正确选择。再一次,我不得不依靠额外的addListener
电话。
虽然我不喜欢选项 3,但这是我选择的选项。但又一次感觉不对劲。代码开始变得杂乱无章,我在应用程序中将它们编码为接口的服务和工厂,这意味着每个实现都有额外的类。
我的问题是:你觉得这样好吗?
注意:我不想使用 mvvmFX 框架,因为我不喜欢所有的魔法并且也过于依赖反射。
(对不起我的英语,但我不是母语人士)