views:

586

answers:

3

Hi

I can see how Swing uses Decorator and Observer pattern.

Observer: Every component(fx JButton) is a subject which can add observers(ActionListeners). When someone pushes a button it notifies all its ActionListeners by calling their actionPerformed(ActionEvent e).

But how about Command Pattern? When I am making classes that implements ActionListener (fx MyActionListener) the actionPerformed(ActionEvent e) is now the execute command? It confuses me that actionPerformed(ActionEvent e) is used both as a execute() and a update() method. Am I right here?

A: 

Interesting take on it and you might be right, but I see it as something that's performed, period. The reason for the action being performed can be a state change, or a mouse click, but it's still a Command in the Command Pattern sense.

Allain Lalonde
+4  A: 

Here is an article that will help. Basically, it is saying you can create concrete command classes that interact with a target object by deriving the ActionListener. Then you can expand what an action event invoker will do by registering these decoupled commands to it.

Chap
Thx. Was very helpfull :)
bobjink
+2  A: 

Yes, so basically making an object that encapsulates the behavior and other information that is needed when an action takes place can be seen as using the command pattern.

The Wikipedia article linked above uses the Action interface as an example of the command pattern in Swing. The Action interface is a subinterface of ActionListener, so a class that implements Action will have to implement the actionPerformed method.

Therefore, a class implementing Action will be encapsulating some operations which will be performed when an action occurs. And that class itself can be seen to follow the command pattern.

When it comes to the implementation, in general, an AbstractAction can be easier to use than implementing Action as it has several methods that needs to be overridden. An example using AbstractAction can be:

class MySpecialAction extends AbstractAction {
    @Override
    public void actionPerformed(ActionEvent e) {
        // Perform operations.
    }
}

The MySpecialAction is a command pattern object -- it has the behavior it must exhibit when an action takes place. When instantiating the above class, one could try the following:

MySpecialAction action = new MySpecialAction("Special Action", mySpecialIcon);

Then, the action can be registered to multiple components, such as JButtons, JMenuItems and such. In each case, the same MySpecialAction object will be called:

JMenuItem specialMenuItem = new JMenuItem(action);

/* ... */

JButton b = new JButton(action);

In both cases, the action that is associated with each component, the button and the menu item, refer to the same MySpecialAction action object, or command. As we can see, the MySpecialAction object is functioning as a object following the command pattern, as it encapsulates some action to be performed at a the time when an action takes place.

coobird
Thank you very much. I get it :)But let’s say I wanted to be able to undo. If i make a interface UndoableAction that extends the interface Action with undo() method. Then JButton b = new JButton(new MyUndoableAction()); would still not have undo functionality.
bobjink
Ehm by that I mean, Swing can't possible know that there is a undo method. actionPerfomed() gets called automaticly when a button is pressed.
bobjink
@bobjink: Yes, the JButton is expecting an Action rather than an MyUndoableAction, so it doesn't know how to "undo", and it will never call the undo() method. The objects to which the MyUndoableAction is handed off to needs to know how to implement the undo. I can't point to a good resource, but I suspect there are quite a few how-to's for implementing an undo. (continued...)
coobird
@bobjink: The text component features page has a way to implement an undo/redo for text components. Maybe that can be a hint as to a way to implement a undo/redo. --> http://java.sun.com/docs/books/tutorial/uiswing/components/generaltext.html#undo
coobird
@bobjink: If you created an abstract class that had undo-able functionailty (and implements the ActionListener) and registers itself to some kind of undo-able list when an action is performed, then derive your concrete commands from this abstract class...it wouldn't be too hard to get undo-able commands. If that doesn't make sense, post a question about undo-able commands and you might get more detail.
Chap