In most cases there is not much difference to offer one over the other.
I would say: if the cases are similar, put them together, but only to name the appropriate method:
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 ();
Thus, you can easily and simply call methods, regardless of the event, perhaps from the scope of testing or to cancel / redo. Obviously, the overall picture is obvious.
In very rare cases, you may be interested in not registering individual events and sources independently. Then one listener on an ActionEvent seems more appropriate.
From the point of view of pure OOP, I think that one listener per button (for example) is more straightforward, and out of a desire to optimize the simulation I do not feel comfortable with 20 or 40 ActionListeners, but in my rational moments, I do not believe that 40 ActionListeners have noticeable effect. But they clutter up your file system, your IDE browser, so I guess there is a reasonable reason in the end to reduce the number of listeners.
The regular receiver is easy to use with the factory button:
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); } 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 convenient.