我正在使用Swing和MVC设计模式创建Java应用程序。

该应用程序的设计如下:


有一个扩展了QuizPanel的类JPanel。该面板是保存我的应用程序主“屏幕”的容器。
我的应用程序的每个“屏幕”都是扩展JPanel的单独类。这些JPanel可以根据需要从QuizPanel添加/删除。
顶级QuizPanel实现我的接口SwitchableSwitchable接口由单个SwitchView(ViewState state)方法组成。我将this传递给在QuizPanel顶级面板中实例化的每个“屏幕”,因此当按下按钮时,他们可以调用SwitchView


在登录屏幕上,用户输入密码和学生ID,如果这些ID与数据库中的令牌匹配,则我需要将Token对象传递到应用程序的另一个屏幕(我尚未实现的问题屏幕)或以某种方式提供它。从嵌入式Derby数据库中检索令牌。

我能想到的唯一方法是创建一个带有静态Token变量的实用程序类,其他类可以访问该变量(这似乎是一种讨厌的方法)。因为我的应用程序设计有缺陷,我是否对此感到麻烦?我可以使用任何技术在应用程序的不同屏幕之间传递Token吗?

主要

public static void main(String[] args) {
    QuizPanel quizPanel = new QuizPanel();

    JFrame frame = new JFrame("Quiz");
    frame.setPreferredSize(new Dimension(400, 400));
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(quizPanel);
    frame.pack();
    frame.setLocationRelativeTo(null);

    frame.setVisible(true);
}


QuizPanel类

public class QuizPanel extends JPanel implements Switchable{

    private MainMenuPane mainMenuPane;
    private RegisterPane registerPane;
    private LoginPane loginPane;

    public QuizPanel() {
        setLayout(new BorderLayout());

        registerPane = new RegisterPane();
        RegisterController registerController = new RegisterController(registerPane, this);

        mainMenuPane = new MainMenuPane();
        MainMenuController mainMenuController = new MainMenuController(mainMenuPane, this);

        loginPane = new LoginPane();
        LoginController loginController = new LoginController(loginPane, this);

        switchView(ViewState.MAINMENU_STATE);
    }

    @Override
    public void switchView(ViewState state) {
        System.out.println("Changing state: " + state);
        switch (state) {
            case REGISTER_STATE:
                removeAll();
                setLayout(new BorderLayout());
                add(registerPane, BorderLayout.CENTER);
                repaint();
                revalidate();
                break;
            case MAINMENU_STATE:
                removeAll();
                setLayout(new BorderLayout());
                add(mainMenuPane, BorderLayout.CENTER);
                repaint();
                revalidate();
                break;
            case LOGIN_STATE:
                removeAll();
                setLayout(new BorderLayout());
                add(loginPane, BorderLayout.CENTER);
                repaint();
                revalidate();
                break;
            default:
                System.out.println("UNREGISTERED STATE!");
                break;
        }
    }
}


登录控制器

public class LoginController implements ILoginController, ILoginViewObserver {
    private ILoginView view;
    private LoginModel loginModel;
    private Switchable parentView;

    public LoginController(ILoginView view, Switchable parentView) {
        this.view = view;
        this.loginModel = new LoginModel();
        this.parentView = parentView;

        view.addLoginViewObserver(this);
    }

    @Override
    public ILoginView getLoginView() {
        return view;
    }

    @Override
    public void submitButtonWasPressed(Token token) {
        Token verifiedToken = loginModel.verifyToken(token);

        if (verifiedToken != null) {
            System.out.println("Token (" + token.token + ") successfully verified");
            // How can I pass the token to the new JPanel the parent view will be displaying?
        } else {
            System.out.println("Token is invalid");
        }
    }

    @Override
    public void cancelButtonWasPressed() {
        parentView.switchView(ViewState.MAINMENU_STATE);
    }
}


LoginModel类

public class LoginModel {
    private List<Token> tokens;

    public LoginModel() {
        TokenDao tokenAccessObject = new TokenAccessObject();
        tokens = tokenAccessObject.getAllTokens();
    }

    public Token verifyToken(Token providedToken) {
        for (Token token : tokens) {
            if (token.studentID == providedToken.studentID){
                if (token.token.compareTo(providedToken.token) == 0) {
                    return token;
                }
            }
        }
        return null;
    }
}

最佳答案

我认为在这种情况下,您可以使用Singleton pattern。该模式应尽可能少用,但在您的情况下(必须从不同应用程序类访问的公共信息),您可以使用它(恕我直言)。

但是,您也可以使用一种Swing功能。


任何Swing窗口都有一个根窗格。然后放置的每个JComponent
在窗口中可以访问此窗格。
JComponent还可以在地图中存储一些用户数据,
称为“客户端属性”。因为JRootPane扩展了JComponent
您可以存储/检索令牌是这张地图。


这是一个简单的代码:

public class TokenUtils {

    private static final String TOKEN_PROPERTY = "token";

    public static Token findToken(JComponent component) {
        JRootPane root = component.getRootPane();
        if (root != null) {
            return Token.class.cast(root.getClientProperty(TOKEN_PROPERTY));
        }
       return null;
    }

    public static void putToken(JComponent component, Token token) {
        JRootPane root = component.getRootPane();
        if (root != null) {
            root.putClientProperty(TOKEN_PROPERTY, token);
        }
    }
}


重要提示:如果使用多个窗口,则必须将令牌放入每个窗口中。

09-27 20:31