Encapsulating Behavior in Components
The first way to handle events locally to a Component requires that you
subclass the Component and override mouseDown, action, or whatever the event
of interest is. For example, creating a Button that handles action is
straightforward:
class OkButton extends Button {
public boolean action(Event e, Object arg) {
// desire behavior
}
}
This approach encapsulates the desired behavior within the Button object, but requires that you create a new class for each new desired behavior--a tedius proposition considering how many components a typical GUI has. Further, the behavior of a Component cannot be changed at run-time.
A better solution involves Component observers that allow us to create a single subclass for each Component regardless of the number of different components needed for a GUI. For example, an object that wants to be notified upon a button press could define a ButtonObserver:
interface ButtonObserver {
public void pressed();
}
Then, a special Button could be defined to notify a button observer:
class ButtonWithObserver extends Button {
ButtonObserver observer;
ButtonWithObserver(String label, ButtonObserver o) {
super(label);
observer = o;
}
public boolean action(Event e, Object arg) {
observer.pressed();
return true;
}
}
This approach has the additional benefit that the event-handling behavior can be changed at run-time by changing the observer field.
Here is an applet that employs ButtonObserver and ButtonWithObserver:
Corresponding source code:
import java.applet.*;
import java.awt.*;
public class ButtonEventTest extends Applet
implements ButtonObserver {
public void init() {
ButtonWithObserver b = new ButtonWithObserver("OK", this);
add(b);
}
public void pressed() {
getGraphics().drawString("Pressed", 0, 40);
}
}
The applet itself is considered the button observer and, hence, you must pass "this" to the ButtonWithObserver constructor and implement method pressed in ButtonEventTest. The applet itself is notified when Button b has been pressed.