Java MVC – 我在这里遗漏了什么吗?
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java MVC – 我在这里遗漏了什么吗?,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含6762字,纯文字阅读大概需要10分钟。
内容图文
直接离开我需要为一些冗长的帖子道歉,但这已经困扰了我很长一段时间了.我最近已经阅读了很多关于MVC的内容,以及它如何在Java的Swing世界中占有一席之地,我仍然无法理解为什么这在任何比教程提供的简单玩具示例稍微复杂一点的应用程序中甚至是非常有用的.但是让我从一开始就开始……
我在C#/ .Net 4.0中完成了所有的GUI编程,这个编程并不广泛,但足以让我们对MVVM有一个很好的理解 – 这是MVC的新版本.这是一个非常简单的概念:您使用XAML(类似于comnponents的描述的XML)定义GUI,指定例如表及其模型,文本字段的字符串值.这些绑定对应于您完全单独定义的对象属性.这样,您就可以在视图与世界其他地方之间实现完全脱钩.最重要的是,模型中的所有更改都“几乎”自动触发回相应的控件,事件驱动设计更加集中等等.
现在,回到Java,我们需要使用旧学校的MVC.让我从一个非常简单的例子开始:我正在尝试使用带有两个组合框和一个按钮的面板.在第一个组合中选择值将驱动第二个组合框的值,根据两个组合框中的值选择第二个组合框中的值将调用外部服务,并且该按钮将使用外部服务重置第一个组合中的值同样.如果我使用“我的”方法来做,我会按如下方式进行:
public class TestGUI {
private JComboBox<String> firstCombo;
private JComboBox<String> secondCombo;
private JButton button;
private ExternalReloadService reloadService;
private ExternalProcessingService processingService;
public TestGUI(ExternalReloadService reloadService, ExternalProcessingService processingService) {
initialise();
this.reloadService = reloadService;
this.processingService = processingService;
}
private void initialise() {
firstCombo = new JComboBox<>();
secondCombo = new JComboBox<>();
button = new JButton("Refresh");
firstCombo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String value = (String) ((JComboBox) e.getSource()).getSelectedItem();
reloadSecondCombo(value);
}
});
secondCombo.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals("model")) {
ComboBoxModel model = (ComboBoxModel) evt.getNewValue();
if (model.getSize() == 0) {
String value = (String) model.getSelectedItem();
processValues((String) firstCombo.getSelectedItem(), value);
}
}
}
});
secondCombo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
processValues((String) firstCombo.getSelectedItem(), (String) secondCombo.getSelectedItem());
}
});
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
resetValues()
}
});
}
private void processValues(String selectedItem, String value) {
processingService.process(selectedItem, value);
//possibly do sth with result and update ui
}
private void reloadSecondCombo(String value) {
secondCombo.setModel(new CustomModel(reloadService.reload(value)));
}
private void resetValues() {
//Call other external service to pull default data, possibly from DB
}
}
很明显,这不是一段简单的代码,尽管很短.现在,如果我们使用MVC来做,我的第一步是使用某种控制器,这将完成所有工作,例如
public class TestGUI {
private JComboBox<String> firstCombo;
private JComboBox<String> secondCombo;
private JButton button;
private Constroller controller;
public TestGUI(Controller controller) {
this.controller = controller;
initialise();
}
private void initialise() {
firstCombo = new JComboBox<>();
secondCombo = new JComboBox<>();
button = new JButton("Refresh");
firstCombo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String value = (String) ((JComboBox) e.getSource()).getSelectedItem();
Data d = controller.getReloadedData(value);
//assiign to combobox
}
});
问题1:View不应该知道有关Controller的任何信息,而应该响应模型的更新.
为了克服上述情况,我们可以作为模型.模型只有两个List,每个组合框一个.所以我们有一个模型(完全uselsess),一个视图和控制器……
问题2我们应该如何连线?至少有两种不同的技术:直接与观察者模式
问题3直接接线 – 这不仅仅是将起始设置中的所有内容重写为三个单独的类吗?在这种方法中,View注册一个模型,Controller同时具有视图和模型.它看起来像……
public class TestGUI {
private JComboBox<String> firstCombo;
private JComboBox<String> secondCombo;
private JButton button;
private Model model;
public TestGUI(Model m) {
model = m;
}
public void updateSecondValues(){
model.getSecondValues();
//do sth
}
}
public class Controller {
private TestGUI view;
private Model model;
public reloadSecondValues(){
firstValues = ...//reload using external service
model.setSecondValues(firstValues);
view.updateSecondValues();
}
}
public class Model {
private Set<String> firstValues;
private Set<String> secondValues;
public Set<String> getFirstValues() {
return firstValues;
}
public void setFirstValues(Set<String> firstValues) {
this.firstValues = firstValues;
}
public Set<String> getSecondValues() {
return secondValues;
}
public void setSecondValues(Set<String> secondValues) {
this.secondValues = secondValues;
}
}
这种方式比它需要的更复杂,恕我直言,使模型和控制器始终相互调用:view – > (做某事)控制器 – > (更新自己)视图
问题4观察者模式 – 在我看来这更糟糕,尽管它允许我们分离视图和模型.视图将在模型上注册为侦听器,这将通知视图有关任何更改.那么现在,我们需要一个方法,如:
public void addListener(ViewListener listener);
我们需要一个ViewListener.现在,我们可能有一个带有一些事件参数的方法,但我们不能用一种方法来满足所有场景.例如,View如何知道我们只是更新第二个组合框并且没有重置所有值,或者没有禁用某些东西,或者没有从表中删除项目???因此,我们需要为每次更新提供一个单独的方法(几乎将我们在gui上的方法复制并粘贴到监听器中)使监听器变得庞大.
主要问题
由于我在这里提出了一些问题,我想总结一下.
主要问题1将logincting分成几个对象:如果你想象你有多个面板,有很多控件,你可以拥有所有这些面板的视图,模型和视图,通过允许,通常允许三倍于你通常的类在UI类上完成工作.
主要问题2无论您使用何种布线技术,最终都会在所有对象上添加方法以允许通信,如果只是将所有内容放在UI中,这将是多余的.
由于“将所有内容放在UI中”不是解决方案,我正在努力获得您的帮助和意见.非常感谢你的想法.
解决方法:
我亲自带着观察者模式走了.我认为你夸大了方法的复杂性.
您的模型应该是“无用的”,因为它只包含数据并向感兴趣的听众发送事件.这是整个优势.您可以将任何业务逻辑和需求封装在一个类中,并将其完全独立于任何特定视图进行测试.根据您希望如何显示数据,您甚至可以使用不同的视图重用相同的模型.
控制器负责改变模型.视图从模型接收事件,但是要根据用户输入进行更改,它将通过控制器.这里的优点再次是解耦和可测试性.控制器完全独立于任何GUI组件;它不了解特定的观点.
您的视图表示数据的特定接口,并在其上提供某些操作.构建View需要模型和控制器是完全合适的.视图将在模型上注册其侦听器.在这些听众中,它将更新自己的表示.如果你有一个像样的UI测试框架,你可以模拟这些事件并断言视图已成功更新,而不使用真实模型,这可能需要一些外部服务,如数据库或Web服务.当View中的UI组件接收到他们自己的事件时,他们可以调用Controller – 再次,通过一个良好的测试框架,您可以断言模拟的Controller接收这些事件而不实际调用任何实际操作,例如网络调用.
至于你的反对意见 – 课程数量是红鲱鱼.这是一个比去耦更低的优先级度量.如果您真的想要优化类的数量,请将所有逻辑放在名为Main的类中.添加沟通方法 – 再次,你是解耦的东西.这是OOP的优势之一.
内容总结
以上是互联网集市为您收集整理的Java MVC – 我在这里遗漏了什么吗?全部内容,希望文章能够帮你解决Java MVC – 我在这里遗漏了什么吗?所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。