Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

3 Swing applications designs : which is the best? [closed]

I'm quite new in desktop applications development and I have a pretty big project do deliver this summer. The thing is that the code has to be very clear, so I won't go in (much) trouble when I will update it.

As a result, I want a good "separation of concerns". And the most difficult part to me is the View-Controller separation.

Now, I have read lots of tutorials, discussions etc. And I have designed a mini-app in 3 different ways. The app is simple : click on a button that transform a label to a "Hello world".

What do you think of those 3 designs ?

Is there a better design to meet my expectations ?

Design 1

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);
        }
    });
...}

Controller1.java :

public class Controller1 {
    public Controller1(View1 v){
        this.view = v;
    }

    public void doSomething(){
        this.view.updateLabel("Hello world");
    }

    private View1 view;
}

Design 2

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;
  ...

}

Controller2.java :

public class Controller2 {

        public Controller2(View2 v){
            this.view = v;
        }

        public void doSomething(){
            this.view.updateLabel("Hello world");
        }

        private View2 view;
}

Design 3

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);
    }
...}

Controller3.java :

public class Controller3 {

    public Controller3(View3 v){
        this.view = v;
        this.listener = new MyListener(v);
    }

    private View3 view;
    public MyListener listener;
}

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");
            }
}
like image 764
user777466 Avatar asked Aug 05 '11 17:08

user777466


People also ask

Which is best Swing or JavaFX?

From a Java developer perspective, both technologies are highly useful in writing pluggable UI components. With its vast UI component library, Swing can provide added advantage to the developer, whereas when it comes to design modern and rich internet application, JavaFX can supersede Swing.

Which application is built by Swing in Java?

Java Swing is part of Java Foundation Classes. It is used to create window-based applications which makes it suitable for developing lightweight desktop applications. Java Swing is built on top of an abstract windowing toolkit API purely written in Java programming language.

What is Swing application in Java?

Swing in Java is a lightweight GUI toolkit which has a wide variety of widgets for building optimized window based applications. It is a part of the JFC( Java Foundation Classes). It is build on top of the AWT API and entirely written in java. It is platform independent unlike AWT and has lightweight components.


2 Answers

I don't like any of these designs. You are coupling the controller to the view to tightly. Let's say you wanted to change controller implementation in the future so you would have to go in all your classes and change the class. Instead you should make it injected. There are a lot of libs that can do this for you via annotations like Guice or Spring but I won't go in to those. Here is a better design.

public class View{
private Controller controller;
   public View(Controller controller) {
       this.controller = controller;
   }
}

This a much cleaner design because the view doesn't have to know what the implementation of the controller is. You can later create a subclass and pass that instead.

So now with the above design I think you can see that you shouldn't pass the View to the controller. This is again coupling which is not good. Instead you can pass an onCallback class that will get executed when it is done. Here is code to undersand it

jButton1.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
            controller.doSomething(new Runnable(){
                    public void run(){
                        updateLabel("Hello world");
                    }               
           });
       }
});

Then in your controller do

public void doSomething(Runnable callback){
   // do work
   SwingUtilties.invokeLater(callback);
}

If you look exactly what I have suggested is removing any kind of coupling. The view should not ask for a Controller, it should be given on. The Controller should not know about the view it should just execute a call back. This is important because if you decided to not using Swing, then you wouldn't have all these dependencies on Swing package in your controller.

Hope this all helps!!

like image 68
Amir Raminfar Avatar answered Oct 02 '22 16:10

Amir Raminfar


Deciding which pattern is best depends a lot on the problem you are solving. Swing is already an MVC framework, so you'll have to consider whether adding another layer of indirection on top of it is worth the effort.

Since you are new to UI programming, I suggest you throw together a walking skeleton of your system first, then based on what you learned from that, decide on your architecture. A well-designed architecture makes it easy to test and reuse components. MVP and MVVM are two well-known ways design patterns for UIs.

For your toy problem you could implement either MVP or MVVM as I do below. Keep in mind you also will typically use interfaces between each and will have observers on Model if that can change.

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);
    }
}

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);
    }
}
like image 23
Garrett Hall Avatar answered Oct 02 '22 18:10

Garrett Hall