Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ActionListener best practices [closed]


Sorry for the title, probably too generic.

I already read How to Write an Action Listener tutorial by Java and I already read this question, but I still have some doubts: I was wondering which solution is the best when I have to perform the same action multiple time.

I'd want to reuse the same ActionListener, but I am not sure on how to achieve this in the best way (speaking in term of: code readability, code mantainability, performance and code style).

First the "standard" code (which I would use if I'm not going to reuse the action listener):

btnMenu.addActionListener(
    new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            Navigator.showMenu();
        }
    }
);

This way I can't reuse anything obv, since it's an anonymous inner class...

Now, I can think of the following solutions:

  1. Store a reference of an Anonymous Inner Class in a field (that will most likely be static final);
  2. Write a new class that implements ActionListener interface.

Example code for solution 1:

public static final MENU_ACTION_LISTENER = new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        Navigator.showMenu();
    }
};

btnMenu.addActionListener(MENU_ACTION_LISTENER);

Example code for solution 2:

// package-private, only GUI-package classes should be able to use it.
// most likely I won't ever need to subclass it, so why not making it final?
final class MenuActionListener implements ActionListener  {
    public void actionPerformed(ActionEvent e) {
        Navigator.showMenu();
    }
}

// now, wherever I need to use it:
btnMenu.addActionListener(new MenuActionListener());

I have some doubts about both solutions:

  1. Where to store references to Anonymous Action Listeners? I could have a sort of utility class (e.g. ActionListenersUtil) where store all action listeners I want to reuse in static final fields, but I don't like it... it seems to me poor design.

  2. It makes more sense, probably best follows the Command Pattern... I initially had some doubt about the packages... I'd like to have all listeners in a separate package (e.g. com.myapp.gui for gui elements and com.myapp.gui.listeners for listeners. But when I wrote down this I realized that I have no choice: the only place where it make sense is in the same package (because they must be package-private), even if for the sake of order I would have like to put them all in a separate package. I still have some doubt though, because most action listeners may be reusable even in case GUI changes; it still would be a good idea to have it in the same package?

Another question: what's the difference between calling btnMenu.addActionListener(MENU_ACTION_LISTENER); and btnMenu.addActionListener(new MenuActionListener()); (speaking in term of JVM, class loading, class compiling, memory occupied by each class, garbage collection and so on)?

Please help, I'm so confused right now! :(

like image 941
kelo Avatar asked Sep 17 '12 16:09

kelo


1 Answers

The best way is to create an Action instead of an ActionListener if you have to attach it to buttons, menus, ... . An Action is the model of a JButton, and the model is meant to be shared

This also gives you the ability to change the text, icon, enabled status, and other properties of all the buttons that the Action is attached to at the same time without multiple calls. Plus, it can be attached to menu items and such as well.

To create an Action you do not have to start from scratch. AbstractAction is a good starting point. The Swing Action tutorial is also a good read.

like image 136
Robin Avatar answered Sep 29 '22 23:09

Robin