Java 使用多线程MVC重新创建具有多个独立仪表的平面仪表板

Java 使用多线程MVC重新创建具有多个独立仪表的平面仪表板,java,multithreading,swing,model-view-controller,Java,Multithreading,Swing,Model View Controller,我正在寻找MVC设计方面的帮助,我哪里出了问题,如果我的进展缓慢,这一切都有意义的话 我正在尝试创建如下内容: 许多仪表可以在自己的线程中工作,我的问题是如何正确地将这个程序划分为视图和模型 以下是我到目前为止的想法: Controllers DashboardController Models BarGaugeModel CircularGaugeModel Views Components

我正在寻找MVC设计方面的帮助,我哪里出了问题,如果我的进展缓慢,这一切都有意义的话

我正在尝试创建如下内容:

许多仪表可以在自己的线程中工作,我的问题是如何正确地将这个程序划分为视图和模型

以下是我到目前为止的想法:

Controllers
           DashboardController
Models
           BarGaugeModel
           CircularGaugeModel
Views
           Components
                   BarGauge
                   CircularGauge
           DashboardView
ViewModels
           DashboardViewModel
Main
           Main
bargagemodel.java

public class BarGaugeModel {
    private int speed;

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }
}
public class BarGauge extends JPanel {
    private JLabel speed = new JLabel();


    public int getSpeed() {
        return Integer.parseInt(speed.getText());
    }

    public void setSpeed(int speed) {
        this.speed.setText(speed+"");
    }
}
public class Main {

    public static void main(String[] args) {
        DashboardView dashboardView = new DashboardView();
        DashboardViewModel dashboardViewModel = new DashboardViewModel();
        DashboardController dashboardController = new DashboardController(dashboardView, dashboardViewModel);

        dashboardView.setVisible(true);
    }
}
仪表板视图模型.java(将由所有模型组成)

BarGauge.java

public class BarGaugeModel {
    private int speed;

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }
}
public class BarGauge extends JPanel {
    private JLabel speed = new JLabel();


    public int getSpeed() {
        return Integer.parseInt(speed.getText());
    }

    public void setSpeed(int speed) {
        this.speed.setText(speed+"");
    }
}
public class Main {

    public static void main(String[] args) {
        DashboardView dashboardView = new DashboardView();
        DashboardViewModel dashboardViewModel = new DashboardViewModel();
        DashboardController dashboardController = new DashboardController(dashboardView, dashboardViewModel);

        dashboardView.setVisible(true);
    }
}
DashboardView.java(将创建所有视图组件并添加到此jframe)

Main.java

public class BarGaugeModel {
    private int speed;

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }
}
public class BarGauge extends JPanel {
    private JLabel speed = new JLabel();


    public int getSpeed() {
        return Integer.parseInt(speed.getText());
    }

    public void setSpeed(int speed) {
        this.speed.setText(speed+"");
    }
}
public class Main {

    public static void main(String[] args) {
        DashboardView dashboardView = new DashboardView();
        DashboardViewModel dashboardViewModel = new DashboardViewModel();
        DashboardController dashboardController = new DashboardController(dashboardView, dashboardViewModel);

        dashboardView.setVisible(true);
    }
}

每个仪表都有一个手动输入供用户输入,我也不太确定输入应该包含在哪个视图中,或者可能包含在完全独立的视图中。

首先,在纯MVC中,模型和视图互不了解,这一切都由控制器控制,控制器充当它们之间的路由器,侦听更改并在视图和模型之间来回转发这些更新

作为一条一般性建议,您应该从定义需要由模型、控制器和视图维护的契约开始,以便它们协同工作。就个人而言,我从
接口开始,因为这将解耦实现细节,并迫使您关注“真正”需要做什么,而不是“可以”做什么由于实现的副作用(例如,控制器能够从视图中添加/删除组件),所以执行此操作

这还应该包括所有观察者模式/侦听器,它们是为通信提供通知通道所必需的

您可能还需要定义什么是线程安全的,什么不是线程安全的,例如,当您的“终极”设计可能需要模型从不同的线程获取信息时,更新应该在相同的线程上生成还是应该同步回单个线程?不管怎样,谁的责任是真正做到这一点(提示,在大多数情况下,这是视图的责任)

通过这个过程,您应该寻找重叠的细节,这些细节可以进一步简化为通用功能(在大多数情况下,当可以将两个不同的模型分解为一个通用的
接口时,没有两个不同的模型具有
public int getValue()
。)

当你不需要转换“数据”时,我也会很小心,例如在你的
BarGauge
类中,你会以
int
的形式计算速度,但把它转换成
字符串
,就我个人而言,我会把它作为
int
,简单地改变你呈现它的方式,它省去了很多麻烦,视图的责任应该是显示状态,所以我倾向于保持原始格式,只在需要时转换为显示

当我做这样的事情时,我试着做的事情之一就是关注谁对什么负责,例如

当更新来自线程时,它将进入模型,模型根据线程的输入更新其状态,它通知控制器,控制器通知视图,然后更新视图

Thread->Model->Controller->View

public interface View {
    public JComponent getView();
}

public interface Controller<M, V extends View> {
    public M getModel()
    public V getView();
}
当用户输入数据时,数据通过视图传递给控制器,控制器通知模型,模型更新其状态,这反过来可能会生成一个回程,以便视图可以根据模型决定对输入执行的操作(即拒绝或修改它,或因为它更新了模型的某些其他状态)更新自身

User->View->Controller->Model{->Controller->View}

将视图划分为更小的视图,然后将其重新组合在一起,将视图组件创建为JPanel作为简单的仪表,然后将它们组合到JFrame中的一个视图中,如我在问题中所示,这有意义吗

一般来说,是的,但您需要了解的一点是,视图可以充当其他控制器的控制器-这意味着您可以有一个“控制面板”视图,它实际上是其他仪表控件的容器(假设您允许控制器公开视图和模型)

我要做的是,从
控制器的基本概念开始(可能还有
视图

公共界面视图{
公共JComponent getView();
}
公共接口控制器{
公共M getModel()
public V getView();
}

这意味着我可以将任意数量的“控制器”传递给我的“控制面板”视图,它可以获取每个“视图”,并将它们添加到自身中以显示。。。作为一个基本概念。

首先,在纯MVC中,模型和视图互不了解,这一切都由控制器控制,控制器充当它们之间的路由器,侦听更改并在视图和模型之间来回转发这些更新

作为一条一般性建议,您应该从定义需要由模型、控制器和视图维护的契约开始,以便它们协同工作。就个人而言,我从
接口开始,因为这将解耦实现细节,并迫使您关注“真正”需要做什么,而不是“可以”做什么由于实现的副作用(例如,控制器能够从视图中添加/删除组件),所以执行此操作

这还应该包括所有观察者模式/侦听器,它们是为通信提供通知通道所必需的

您可能还需要定义什么是线程安全的,什么不是线程安全的,例如,当您的“最终”设计可能需要模型从不同的线程获取信息时,更新是在相同的线程上生成还是在bac上同步