MVC(Model-View-Controller)和 MVVM(Model-View-ViewModel)都是设计模式,用于帮助开发人员更好地组织和管理应用程序的代码。尽管它们在名称上有相似之处,但在实现细节和适用场景上有所不同。
1、Model(模型)
○ 负责管理应用程序的数据和业务逻辑。
○ 包括数据访问和数据处理逻辑。
2、View(视图)
○ 负责展示数据。
○ 通常是指用户界面(UI)。
3、Controller(控制器)
○ 负责处理用户的输入,并将数据传递给 Model 层进行处理。
○ 控制器还负责更新 View 层的状态。
● 用户与 View 交互。
● Controller 接收到用户的输入,并调用 Model 层的方法。
● Model 层处理数据,并将结果返回给 Controller。
● Controller 更新 View 层的状态,使其反映新的数据状态。
● 数据流:通常是单向的,即从 View 到 Controller 再到 Model,最后再返回到 View。
● 依赖关系:View 依赖于 Controller,Controller 依赖于 Model。
● 测试性:Controller 和 Model 较容易测试,因为它们不依赖于具体的 UI 实现。
● 用户与 View 交互。
● View 通过数据绑定直接与 ViewModel 交互。
● ViewModel 负责与 Model 层进行数据交换,并处理业务逻辑。
● ViewModel 的数据变化会自动反映到 View 上,反之亦然。
特点
● 数据绑定:MVVM 强调数据绑定,即 View 和 ViewModel 之间的数据是双向绑定的。
● 依赖关系:View 依赖于 ViewModel,ViewModel 依赖于 Model。
● 测试性:ViewModel 更容易进行单元测试,因为它不依赖于具体的 UI 实现。
// Model
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}}
// View
public class LoginView {
private JTextField usernameField;
private JPasswordField passwordField;
private JButton loginButton;
public LoginView() {
// 初始化界面组件
usernameField = new JTextField();
passwordField = new JPasswordField();
loginButton = new JButton("Login");
// 设置布局和事件监听器
JPanel panel = new JPanel(new GridLayout(3, 1));
panel.add(new JLabel("Username:"));
panel.add(usernameField);
panel.add(new JLabel("Password:"));
panel.add(passwordField);
panel.add(loginButton);
JFrame frame = new JFrame("Login Form");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.pack();
frame.setVisible(true);
}
}
// Controller
public class LoginController {
private User user;
private LoginView loginView;
public LoginController(User user, LoginView loginView) {
this.user = user;
this.loginView = loginView;
loginView.getLoginButton().addActionListener(e -> handleLogin());
}
private void handleLogin() {
String username = loginView.getUsernameField().getText();
String password = new String(loginView.getPasswordField().getPassword());
user.setUsername(username);
user.setPassword(password);
if (user.getUsername().equals("admin") && user.getPassword().equals("password")) {
JOptionPane.showMessageDialog(loginView, "Login successful!");
} else {
JOptionPane.showMessageDialog(loginView, "Invalid credentials.");
}
}
}
// Model
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
// ViewModel
public class LoginViewModel {
private User user = new User();
public String getUsername() {
return user.getUsername();
}
public void setUsername(String username) {
user.setUsername(username);
}
public String getPassword() {
return user.getPassword();
}
public void setPassword(String password) {
user.setPassword(password);
}
public void login() {
if (user.getUsername().equals("admin") && user.getPassword().equals("password")) {
JOptionPane.showMessageDialog(null, "Login successful!");
} else {
JOptionPane.showMessageDialog(null, "Invalid credentials.");
}
}
}
// View
public class LoginView extends JFrame {
private LoginViewModel viewModel;
private JTextField usernameField;
private JPasswordField passwordField;
private JButton loginButton;
public LoginView(LoginViewModel viewModel) {
this.viewModel = viewModel;
// 初始化界面组件
usernameField = new JTextField();
passwordField = new JPasswordField();
loginButton = new JButton("Login");
// 设置布局和事件监听器
JPanel panel = new JPanel(new GridLayout(3, 1));
panel.add(new JLabel("Username:"));
panel.add(usernameField);
panel.add(new JLabel("Password:"));
panel.add(passwordField);
panel.add(loginButton);
add(panel);
pack();
setVisible(true);
// 数据绑定
usernameField.setText(viewModel.getUsername());
passwordField.setText(viewModel.getPassword());
usernameField.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
viewModel.setUsername(usernameField.getText());
}
public void removeUpdate(DocumentEvent e) {
viewModel.setUsername(usernameField.getText());
}
public void changedUpdate(DocumentEvent e) {
viewModel.setUsername(usernameField.getText());
}
});
passwordField.getDocument().addDocumentListener(new DocumentListener() {
public void insertUpdate(DocumentEvent e) {
viewModel.setPassword(new String(passwordField.getPassword()));
}
public void removeUpdate(DocumentEvent e) {
viewModel.setPassword(new String(passwordField.getPassword()));
}
public void changedUpdate(DocumentEvent e) {
viewModel.setPassword(new String(passwordField.getPassword()));
}
});
loginButton.addActionListener(e -> viewModel.login());
}
}
总结
● MVC:强调控制器的作用,视图和模型之间的交互需要通过控制器来完成。
● MVVM:强调数据绑定,视图和视图模型之间的交互是自动的,通过数据绑定机制实现。