use*_*466 15 java architecture model-view-controller swing
我是桌面应用程序开发的新手,今年夏天我有一个非常大的项目.问题是代码必须非常清晰,所以当我更新代码时,我不会遇到麻烦.
结果,我想要一个良好的"关注点分离".对我来说最困难的部分是视图 - 控制器分离.
现在,我已经阅读了很多教程,讨论等.我已经以3种不同的方式设计了一个迷你应用程序.该应用程序很简单:单击将标签转换为"Hello world"的按钮.
你怎么看待这3个设计?
有没有更好的设计来满足我的期望?
View1.java:
public View1() {
initComponents();
this.controller = new Controller1(this);
}
private Controller1 controller;
public void updateLabel(String message){
this.jLabel1.setText(message);
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
this.controller.doSomething();
}
private void initComponents() {
...
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
...}
Run Code Online (Sandbox Code Playgroud)
Controller1.java:
public class Controller1 {
public Controller1(View1 v){
this.view = v;
}
public void doSomething(){
this.view.updateLabel("Hello world");
}
private View1 view;
}
Run Code Online (Sandbox Code Playgroud)
View2.java:
public View2() {
initComponents();
this.controller = new Controller2(this);
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
controller.doSomething();
}
});
}
public void updateLabel(String message){
this.jLabel1.setText(message);
}
private Controller2 controller;
...
Run Code Online (Sandbox Code Playgroud)
}
Controller2.java:
public class Controller2 {
public Controller2(View2 v){
this.view = v;
}
public void doSomething(){
this.view.updateLabel("Hello world");
}
private View2 view;
}
Run Code Online (Sandbox Code Playgroud)
View3.java:
public View3() {
initComponents();
this.controller = new Controller3(this);
this.jButton1.addActionListener(this.controller.listener);
}
private Controller3 controller;
public void updateLabel(String message){
this.jLabel1.setText(message);
}
...}
Run Code Online (Sandbox Code Playgroud)
Controller3.java:
public class Controller3 {
public Controller3(View3 v){
this.view = v;
this.listener = new MyListener(v);
}
private View3 view;
public MyListener listener;
}
Run Code Online (Sandbox Code Playgroud)
MyListener.java:
public class MyListener implements ActionListener{
private View3 view;
public MyListener(View3 v){
this.view = v;
}
public void actionPerformed(java.awt.event.ActionEvent evt) {
this.view.updateLabel("Hello world");
}
}
Run Code Online (Sandbox Code Playgroud)
Ami*_*far 10
我不喜欢这些设计.您将控制器与视图紧密耦合.假设您希望将来更改控制器实现,因此您必须进入所有类并更改类.相反,你应该注入它.有很多lib可以通过Guice或Spring这样的注释为你做这些,但我不会去那些.这是一个更好的设计.
public class View{
private Controller controller;
public View(Controller controller) {
this.controller = controller;
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个更清洁的设计,因为视图不必知道控制器的实现是什么.您可以稍后创建一个子类并传递它.
所以现在通过上面的设计,我认为你可以看到你不应该将View传递给控制器.这又是耦合,这是不好的.相反,你可以传递一个onCallback类,它将在完成后执行.这是代码来代替它
jButton1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
controller.doSomething(new Runnable(){
public void run(){
updateLabel("Hello world");
}
});
}
});
Run Code Online (Sandbox Code Playgroud)
然后在你的控制器做
public void doSomething(Runnable callback){
// do work
SwingUtilties.invokeLater(callback);
}
Run Code Online (Sandbox Code Playgroud)
如果你看起来我建议删除任何类型的耦合.该视图不应该要求控制器,应该给予它.Controller不应该知道应该只执行回调的视图.这很重要,因为如果您决定不使用Swing,那么您的控制器中的Swing包就不会具有所有这些依赖关系.
希望这一切都有帮助!!
确定哪种模式最佳取决于您正在解决的问题. Swing已经是一个MVC框架,因此您必须考虑在其上添加另一层间接是否值得付出努力.
由于您是UI编程的新手,我建议您先将系统的步骤框架放在一起,然后根据您从中学到的内容,决定您的架构.精心设计的架构使测试和重用组件变得容易. MVP和MVVM是两种众所周知的UI设计模式.
对于你的玩具问题,你可以像我一样实现MVP或MVVM.请记住,您通常也会在每个接口之间使用接口,如果可以更改,则会在Model上有观察者.
MVP
public class Model {
public String getWhatIWantToSay() {
return "Hello World";
}
}
public class Presenter implements ActionListener {
private final View view;
private final Model model;
public Presenter(Model model, View view) {
this.model = model;
this.view = view;
view.addButtonListener(this);
}
public void actionPerformed(ActionEvent e) {
view.setText(model.getWhatIWantToSay());
}
}
public class View {
private JButton button = new JButton();
private JLabel label = new JLabel();
public void addButtonListener(ActionListener listener) {
button.addActionListener(listener);
}
public void setText(String text) {
label.setText(text);
}
}
Run Code Online (Sandbox Code Playgroud)
MVVP
public class ModelView extends Observable {
private final Model model;
private String text = "";
public ModelView(Model model) {
this.model = model;
}
public void buttonClicked() {
text = model.getWhatIWantToSay();
notifyObservers();
}
}
public class View implements Observer {
private JButton button = new JButton();
private JLabel label = new JLabel();
private final ModelView modelView;
public View(final ModelView modelView) {
this.modelView = modelView;
modelView.addObserver(this);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
modelView.buttonClicked();
}
});
}
public void update(Observable o, Object arg) {
label.setText(modelView.text);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3658 次 |
| 最近记录: |