2012-04-23 8 views
2

我目前正在用Java编程21点应用程序,它需要写在MVC架构中。我有我的所有模型,视图和控制器完全编码,一切都完美。然而,我想知道将听众附加到组件上的最佳方式是什么(例如JButton)。在MVC体系结构中公开诸如JButton等Java组件的最佳方式是什么?

我当前的设计声明视图中需要侦听器作为公共final的所有组件。然后它将视图传递给控制器​​。从那里,控制器可以完全访问组件并添加动作侦听器。代码示例:

public class View extends JFrame { 
    public final JButton myBtn1 = new JButton("Button 1"); 
    public final JButton myBtn2 = new JButton("Button 2"); 

    public View() { 
     //constructor code here.... 
    } 
} 

public class Controller { 
    private Model myModel; 
    private View myView; 

    public Controller(Model m, View v) { 
     myModel = m; 
     myView = v; 

     //now add listeners to components... 

     myView.myBtn1.addActionListener(new MyActionListener1()); 
     myView.myBtn2.addActionListener(new MyActionListener2()); 
    } 
} 

然而,我的一个朋友宣布他所有JButton的私人范围,然后做出视野中的公共方法来添加动作侦听到它们各自的部件。对我来说,这只是浪费时间,只会增加不必要的代码。代码示例:

public class View extends JFrame { 
    private JButton myBtn1 = new JButton("Button 1"); 
    private JButton myBtn2 = new JButton("Button 2"); 

    public View() { 
     //constructor code here.... 
    } 

    public void myBtn1AddActionListener(ActionListener a) { 
     myBtn1.addActionListener(a); 
    } 

    public void myBtn2AddActionListener(ActionListener a) { 
     myBtn2.addActionListener(a); 
    } 

    //etc etc... 
} 

public class Controller { 
    private Model myModel; 
    private View myView; 

    public Controller(Model m, View v) { 
     myModel = m; 
     myView = v; 

     //now add listeners to components... 

     myView.myBtn1AddActionListener(new MyActionListener1()); 
     myView.myBtn2AddActionListener(new MyActionListener2()); 
    } 
} 

那么,考虑到上述两种情况,哪种方式更好?

谢谢。

+1

'需要写入MVC架构'?如果这是一个家庭作业/课程作业的问题,在这里很好,但它标记为家庭作业,所以人们知道建议你/让你觉得,而不仅仅是为你做;) – ChrisW 2012-04-23 17:54:27

+1

哈哈,好吧,我不是要求人们为我做 - 如我所说,它工作得很好。这只是一个'最佳实践'的问题,真的...... :-) – tjramage 2012-04-23 18:08:45

回答

4

注意:这个答案是我个人的意见。我仍然需要找到有关编写Swing UI并将其与业务逻辑关联起来的“最佳/最推荐”方式的体面文献。但直到我发现,我使用常识和个人经验。

我想说两者都不是实现这个的正确方法。在MVC中,视图就是您向用户提供视觉信息的部分。但是,按下按钮时在ActionListener中触发的代码是属于控制器的代码,因为它很可能是业务逻辑(这是根据您的代码片段做出的假设。如果您的按钮只是执行一个UI操作(如启用另一个组件),则动作侦听器应该完全包含在视图)中。

所以我会在控制器中公开这些方法,例如如果您目前有一个ActionListener

public void actionPerformed(ActionEvent e){ 
    doSomeStuff(UI info, event info); 
} 

其中信息从事件中获得的视图和event info信息获得UI info,我会介绍控制器

public void doSomeStuff(UI info, event info) 

的公共方法和调用方法从视图。这有两个主要好处:

  1. 只有从视图到控制器的依赖关系,而不是从控制器到视图。如果控制器包含业务逻辑,则不希望为了更多SwingUI而重用该代码。在这里不需要依赖于Swing类。一个例子可以是单元测试。如果您的控制器不依赖于用户界面,那么您可以轻松地测试应用程序的控制器模型部分,并且可以像使用UI调用这些调用时那样使用API​​遵循相同的代码路径。
  2. 您可以完全调整您的用户界面,并决定将另一个组件替换为您不能附加ActionListener而不必重写控制器和视图的组件。

编辑

虽然我认为我的文章的上述部分仍然有效,我必须阅读trashgod的回答提到了Wikipedia MVC page(他在评论中提及了)后承认,上面只是对MVC模式的一种解释以及如何在Swing应用程序中实现这一点。

望着那Wiki页面,它在MVC定义了三个部分,(总结):

  • 型号:管理行为和应用领域
  • 查看的数据:呈现模型转换为适合交互的形式,通常是用户界面元素
  • 控制器:接收用户输入并通过在模型对象上发起调用来启动响应

我的解释/意见/首选方式是有一个模型和一个控制器,如果需要多个视图(或例如在测试零视图)。控制器不直接接收用户输入(这相当于让它在视图上注册监听器),而是提供API挂钩来传递用户输入。这提供了一种可以处理用户输入的“抽象控制器”,但该视图仍然需要将真实的用户输入事件转换为控制器可理解的事件/信息。所以这意味着我可以轻松地创建MVC的测试“视图”一侧以及真正的“视图”一侧,而无需更改控制器或模型中的任何内容。

另一种解释是在控制器和视图之间有一个更紧密的耦合(他们真的相互依赖)。这也意味着,如果您决定从Swing UI视图切换到命令行视图,则可能必须更改控制器。这是好还是坏?我认为这是个人品味的问题。

我最初的答案中唯一不太好的是我在控制器部分找到了业务逻辑,而Wiki页面明确指出它位于模型中。我可能会对一些简单的Ruby on Rails实验感到困惑,因为模型不过是数据访问层。我的不好...

+0

辉煌的东西!在我开始这个项目之前,我无法在网上找到任何东西,这是一种耻辱,因为我宁愿从头开始这样做......无论如何,这真的很有用 - 谢谢你:-) – tjramage 2012-04-23 19:13:26

0

如果你的问题涉及到架构API(目前不是真正的API),那么我认为这两种方法都是不好的,而且在你没有真正的经验和清楚的理解之前不要使用任何模式,因为结果不好。

4

我当前的设计声明了视图中需要侦听器作为public final的所有组件。然后它将视图传递给控制器​​。从那里,控制器可以完全访问组件并添加动作侦听器。代码示例:

不,不要不必要地暴露字段 - 您不应该为了MVC而牺牲封装。出于上述原因,您不应将组件公开。取而代之的是给视图公共方法,控制可以调用,或让视图通过侦听器改变状态到模型。将控件传递给控件的视图和视图,所有交互都应该通过公共方法,而不是通过公开组件或字段。

我已经解决了这个问题,我并不是说最好的或者规范的方法是将Control的一个实例传递给View,并为我的监听器使用匿名内部类,并让这些类呼叫控制方法。例如,

// inside of view 
exitButton.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent evt) { 
     if (control != null) { 
     control.exitAction(); 
     } 
    } 
}); 
+0

本来可以选择这个作为接受的答案,但罗宾的答案要深入一点。尽管如此,感谢您的回答 - 非常感谢:-) – tjramage 2012-04-23 19:15:51

+0

@tjramage:您选择正确的答案是一个很好的决定。他是一个好的和详细的答案。我自己正在投票。用于封装的 – 2012-04-23 19:39:17

+0

+1,例如使用'Action';也考虑让控制器_listen_来查看,就像[这里]建议的(http://stackoverflow.com/a/10257197/230513)。 – trashgod 2012-04-23 20:53:56

1

尽管我个人喜欢你的风格,但你会发现你的朋友的风格(或类似)更像“标准的Java风格”。所以,在一个典型的编程团队中,它会更容易接受。它还具有(可能的)优点(以及可能的陷阱),在某些使用情况下,按钮可以被不同的按钮替换。

+0

啊,好点!谢谢:-) – tjramage 2012-04-23 19:06:18

相关问题