5YrsLaterDBA
5YrsLaterDBA

Reputation: 34740

Best way to implement actionPerformed?

In Java, we have two ways to implement actionPerformed:

  1. One actionPerformed method per class: use if-else to check event source;
  2. Use anonymous inner classes and implement the actionPerformed method in where that object is created;

For option 1, it is easy to keep track of where the actionPerformed code is because there is only one method per class. We can easy locate that method and then look inside to find the code we are looking for. However, there may be too many if-else clauses if we have many action listeners.

For option 2, it is not easy to find where the actionPerformed code is because it is scattered all over the class. If you have many action listeners, it will be more difficult to keep track of the actionPerformed instances.

I personally prefer option 1 because it is much easier to maintain the code, even the performance may be less efficient than option 2.

What are the pros and cons of each method? What else should be taken into consideration when choosing how to implement actionPerformed? Which way do you prefer?

EDIT:

so there is a 3rd option based on the suggestion from A. Lee below. it is a combination of the option 1 and option 2: use anonymous inner classes but put them altogether in ONE place within a class. I think it is a good idea.

Upvotes: 4

Views: 2167

Answers (4)

A Lee
A Lee

Reputation: 8066

I think the long if-else chain in an actionPerformed method is ugly for several reasons - you make unnecessary checks every time to determine which is the appropriate receiver code for the ActionEvent and as the code grows it becomes increasingly unmaintainable.

If you want to have all your action handlers in one place, have an initializeActionListeners method that binds your ActionListeners to your controls. Or bind them where you initialize them so the event handler is closer to your widget/control itself, e.g.,

// not thread-safe
private JLabel getSomeLabel() {
    if (someLabel == null) {
        someLabel = new JLabel("Some label, huh");
        someLabel.addActionListener(...)
    }
    return someLabel;
}

Upvotes: 3

kleopatra
kleopatra

Reputation: 51524

Wrong alternatives: the question is not anonymous classes vs. a long big if-else construct (you can easily have the latter in the former). The question is whether to have a semantically strong class (anonymous or not) which does exactly one job, is the only one that does it ans does it completely. After all, we are in OO-land ;-)

So: strict no-no-ever to any if-then-else structs.

Upvotes: 1

user unknown
user unknown

Reputation: 36229

In most cases, there isn't much difference, to suggest one over the other.

I would say: If the cases are similar, put them together, but only to call the appropriate method from there:

    public void actionPerformed (ActionEvent e)
    {
            String cmd = e.getActionCommand ();
            if (cmd.equals (cmdNextPage))        nextPage ();
            else if (cmd.equals (cmdLastPage))   lastPage ();
            else if (cmd.equals (cmdOk))         ok ();
            // ... and so on

This way, you can call the methods easily, independent from an event, maybe from a testing framework, or for some undo/replay. The common pattern is obviously visible.

In very rare cases you might be interested in unregistering single events, and sources independently. Then, a single listener per ActionEvent seems better suited.

From a pure OOP perspective, I think a single listener per Button (for example) is more straight forward, and from an imature optimization wish, I don't feel comfortable with 20 or 40 ActionListeners, but in my rational moments, I don't believe 40 ActionListeners have a measurable impact. But they clutter up your Filesystem, your IDE-Browser, so I guess there is a rational reason in the end, to keep the number of Listeners low.

A common Listener is easy to use in a button factory:

    private void addButton (JPanel jp, String cmd, String ttt)
    {
            JButton jb = new JButton (cmd);
            jb.setToolTipText (ttt);
            jp.add (jb);
            jb.addActionListener (this);
            buttonlist.add (jb);
    }

    /**   @return a Panel with Action-Buttons.     */
    private JPanel createControlPanel ()
    {
            JPanel m = new JPanel ();
            m.setLayout (new BoxLayout (m, BoxLayout.Y_AXIS));

            JPanel jpc = new JPanel ();
            jpc.setLayout (new FlowLayout ());
            buttonlist = new ArrayList <JButton> ();

            addButton (jpc, cmdLastPage, "last page");
            addButton (jpc, cmdNextPage, "next page");
            addButton (jpc, cmdOk, "save");
            addButton (jpc, cmdEsc, "exit");

It is very easy and clear, where to add a new button and how. I find it very maintainable.

Upvotes: 0

Marcos Vasconcelos
Marcos Vasconcelos

Reputation: 18276

I use a third option, I wrote my own Manager that bind methods to JButtons directly through annotations.

I provide it as a OpenSource project, you can check it on https://github.com/MarkyVasconcelos/Towel/wiki/ActionManager

The pros is that you don't need implement any ActionListener, and don't neeed Anonymous Inner Classes.

All Actions are in the methods of your class.

Upvotes: 0

Related Questions