Java Swing中正确的模型 - 视图 - 控制器模式

时间:2012-08-03 10:27:16

标签: java swing model-view-controller design-patterns jtable

我最近开始使用Java中的Swing应用程序,目前主要使用JTables。来自.NET WPF背景的世界,这是使用MVVM设计模式进行了极大的架构,我正在与Swing进行一些努力。原因是,使用JTables似乎有很多方法可以实现模型 - 视图 - 控制器模式(至少在查看可用类之后我的感受)。因此,我想分享一些可能的一般方法,这些方法可以通过我的思想和目前为止看到的,以及收集您对此问题的评论,这可能适用于其他控件/应用程序:

  1. JTable< - > TableModel:在这种方法中,我们在某种意义上只有View和Model。 TableModel具有有用的更新方法,例如setValueAt,您可以在其中放置任何UI更新的处理代码,并且反过来可以在模型更新上引发事件。我想这是DefaultTableModel的默认实现。因此,模型处理直接在单元格(数据)上进行的更新。 View(JTable)会在作为View的类后面的代码中注册任何其他处理程序。代码可能如下所示:

    类视图扩展了JPanel {

    public View(TableModel model) {
        super(new BorderLayout(1, 0));
        JTable table = new JTable(model) {
    
            //override anything you need here - renderers etc.
    
        };
    
        //add any listeners here
    }
    //Listeners that would perform actions on events, and possibly call model to update
    

    我喜欢这个是我们只有两个地方放置代码,并且在实现中提供的JTable和TableModel之间存在自然连接,即setValueAt方法。 在我看来,我讨厌关于这一点,完全无视MVC模式,在MVVM的情况下,你的代码非常出色地构建了

  2. JTable - >控制器< - > TableModel:添加另一个层来执行逻辑 我们现在有一个中央控制器可以实例化(或接收注入构造函数)视图和模型。此外,它将在视图上注册任何侦听器,并且每当发生这种情况时,我们将在模型上调用一些更新方法。也许另一种方法是将转发事件从视图的注册处理程序转发到控制器,但这需要查看知道关于控制器... 我想当我们调用update方法时,事件返回视图的触发将保留在模型上,除非我们只是在表上调用tableChanged方法。然而,这破坏了事件机制的整体整洁性,这是在TableModel实现中免费提供的...... 此处必须考虑的其他事项是,每当我们从View处理事件时,我们需要注意从视图索引转换为模型索引(可能是我目前无法想到的其他注意事项)

  3. JTable< - > TableModel - > BusinessModel:我们使用TableModel作为协调员,并将我们的业务知识保存在其他地方 到目前为止,我假设TableModel包含原始业务数据,例如List的形式。现在我们可以在TableModel上使用setValueAt方法+寄存器处理程序,随后将修改底层的BusinessModel,封装List。 我唯一担心的是TableModel 应该真的是模型而不是控制器。

  4. 这些是我对此事的看法。我非常期待您的回复和评论。

2 个答案:

答案 0 :(得分:2)

Swing MVC模型,据我所知,它没有严格地将View与模型分开,即两者之间存在一些通信以避免不必要地通过控制器。当我使用它时,JTable是视图,TableModel是模型,并且您的侦听器充当需要更多控制的事物的控制器,而不仅仅是“显示模型中的内容”。

答案 1 :(得分:2)

为了澄清,Swing separable model architecture使用observer pattern将模型与松散地结合起来,如图所示here。通常EventListenerList在内部使用,但提到了其他实现here。 UI委托控制用户与视图的交互。这允许组件在不同平台上正确地工作,如用户所感知的那样。

  

因此模型通过特定的Listener接口向视图组件注册?

不,每个模型都在内部维持EventListenerList;每个相应的视图通过模型的addXxxListener()方法将自身添加为侦听器。大多数组件也使用PropertyChangeLister作为绑定属性。