JAVA 从SWING的Model 初探MVC思想

最近尝试写一个记账的项目来巩固JAVASE的知识,顺便学习真正的项目该如何一点点构建,看了个类似的项目叫一本糊涂账,来自 http://how2j.cn/k/hutubill ,因为没有认真看过swing的知识,所以在用到ComboBox和Table的时候对于ComboBoxModel和TableModel这两个需要写的model有些疑惑。

因为是GUI,又有Model,我就很自觉的想:这个是不是就是天天说的MVC模式?于是google了一下,果然,SWING是MVC的方式写的。我目前的理解是,建一个JTable必须指定一个专门的TableModel来规定该Table的显示时的内部逻辑和规则,TableModel这个接口定义了:

public getColumnCount() //得到列数的规则
public Object getValueAt(int rowIndex, int columnIndex) //得到指定位置的值的规则
public int getRowCount()//得到行数的规则

这个规则是逻辑行为,而JTable创建出来之后,只能按照这个逻辑行为对user进行展示,按照这个发展,Swing的Controller应该是在和View糅合在一起了,毕竟用户跟UI交互的时候又想有业务,又想有界面显示,很难区分。只有把View中的UI和Listener绑定的过程,使得点击某个UI如提交表单时,可以调用相应的Listener这个环节属于Controller吧,我觉得Listener应该不属于Controller,因为Controller应该不涉及对Model具体的调整;UI自然也有View层,它根据Model把内容显示出来。Controller和View都是一些基于Model的方法,没有任何状态!

暂时是这样理解的…

找了很多帖子,明天早上上完课认真看一下,中午再更新。未完待续。

按照上述思路MVC层实现

https://blog.csdn.net/YoutellIdo/article/details/48145755
TestModel.java

package model;

public class TestModel {
    private String message;

    public String getMessage(){
        return message;
    }
    public void setMessage(String message){
        this.message=message;
    }
}

TestView.java

package view;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextArea;

public class TestView extends JPanel{
    private static final long serialVersionUID = 1L;
    private JTextArea textArea;
    private List<ActionListener> listeners;
    public void addActionListener(ActionListener actionlistener){
        listeners.add(actionlistener);
    }
    public void setTextArea(String text){
        textArea.setText(text);
    }

    public TestView() {
        listeners=new ArrayList<ActionListener>();
        setLayout(null);
        textArea=new JTextArea();
        textArea.setBounds(20, 20, 400, 100);
        add(textArea);
        JButton textbtn=new JButton("Show Message");
        textbtn.setBounds(120, 140, 150, 40);
        add(textbtn);
        textbtn.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                for(int i=0;i<listeners.size();++i){
                    listeners.get(i).actionPerformed(e);
                }
            }
        });
    }
}

TestController.java

package controller;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JPanel;

import model.TestModel;
import view.TestView;

public class TestController {
    private TestView testview;
    private TestModel testmodel;

    public TestController() {
        testview=new TestView();
        testmodel=new TestModel();
        testview.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                System.out.println("suc...");
                testmodel.setMessage("test...");
                testview.setTextArea(testmodel.getMessage());
            }
        });

    }
    public JPanel getView(){
        return testview;
    }

    public static void main(String[] args) {
        TestController testcontroller=new TestController();
        JFrame frame=new JFrame("TEST");
        frame.setLayout(new BorderLayout());
        frame.setBounds(100, 100, 450, 300);
        frame.getContentPane().add(testcontroller.getView());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        }
 }

Listener到底属于哪里呢???

这样分层应该是针对Swing目前的设计的MVC了,不过我觉得很奇怪,看了一些别人文章,说永远不应该把UI和Listener在View层中分离,不然UI组件就被暴露在外。那么

StackOverFlow大法好:

原文这样说到,
"Another issue is, you really don’t want to expose UI components to anybody, the controller shouldn’t care how certain actions occur, only that they can.

This would suggest that the ActionListeners attached to your UI controls should be maintained by the view. The view should then alert the controller that some kind of action has occurred. For this, you could use another ActionListener, managed by the view, to which the controller subscribes to."

在这个stackoverflow中的高赞答案中他其实给View层设置了一个接口,该视图将实现一个接口(描述控制器和视图的contact),允许控制器管理它。控制器将向视图注册接口(Listener),以允许在视图中发生某些事件时通知它。该视图将管理它自己的内部事件托管(例如ActionListener),意思就是说实际的Listener还是在View层里,但是是通过Controller来管理的,通过控制器/视图Listener接口,告诉控制器发生了什么事情,这将控制器和视图相互分离…

这里,Controller应该控制View,但是为了让View自己管理自己的具体控件该有什么Listener,View中反而有了一些Controller实例,把View注册给Controller,然后让Controller中的控制方法去调用View中的具体方法…应该是这个意思。
这样只是探讨怎么把Swing里的View和Controller层分离。。说实话分了还不如不分,因为GUI就是这样的特性。所以Swing其实并不是标准的MVC设计,应该叫M +VC,VC揉和在一起…所以刚开始看了一堆从Swing学习MVC的文章,真搞不明白他们为什么非要从Swing开始学。。

上面这两个例子很长,就不贴上来了,有兴趣的直接看

Java and GUI - Where do ActionListeners belong according to MVC pattern?
https://stackoverflow.com/questions/26517856/java-and-gui-where-do-actionlisteners-belong-according-to-mvc-pattern

对MVC本身

经过这些小小的探索和梳理,我觉得MVC这个模式也有一定局限,首先对Model的理解更深了,Model其实就应该是数学建模大赛里所谓的“模型”,这些东西就应该抽象成这个样子,应该是一个一个的JavaBean;所谓View就是怎么展示这些Model,Controller就是用户和View交互的时候,View会通知Controller,Controller再去操作Model层,Controller只是把Model和View跟分离开,然后分别通信,View和Model本身不通信,所以显然Swing不是纯粹的MVC,正常的开发中View跟Model没少通信。然后只有Model真正描述了数据也好,模型也好;Controller和View都是一些操作它的方法。

我还没做过真正的Web项目,目前对Servlet、JSP、DAO、Server还未深刻体验,所以体会不是很深。给出一些关于Web分析的文章,寒假计划开始学习Spring做Web项目,到时候应该会再更一篇。
贴出我看的一些觉得有用的帖子给大家:
FAQ-如何理解 MVC 中的 Model?
https://www.zhihu.com/question/22886622
JavaWeb中的MVC https://blog.csdn.net/weixin_41667774/article/details/79278605
Swing组件中的Model详解,这里提到了Swing是Model-Driven,不是MVC
http://www.52im.net/thread-39-1-1.html
通过Java Swing看透MVC设计模式
http://developer.51cto.com/art/200612/37079.htm

下面这篇我还没看,计划吃完午饭好好看一下,
Learn to make a MVC application with Swing and Java 8
https://www.ssaurel.com/blog/learn-to-make-a-mvc-application-with-swing-and-java-8/

猜你喜欢

转载自blog.csdn.net/u013453787/article/details/84932770