views:

54

answers:

1

I have a class that represents a basic page with "go back", "go forward", and "canel" buttons in Wicket. But not all pages have all the buttons, e. g. the first page doesn't have "go back" obviously.

My idea is to define a generic ActionHandler

public interface ActionHandler {
  void perform();
}

and let subclasses return the actions they support:

public Derived extends BasicPage {
  protected ActionHandler getForwardHandler() {
    return new ActionHandler() {
      void perform() {
        doIt();
      }
    };
  }
}

The question is: why not to use protected fields?

public Derived extends BasicPage {
  protected forwardHandler = new ActionHandler() {
      void perform() {
        doIt();
      }
    };
}

Another option would be not to use inheritance (which doesn't make really sense here) and set the ActionHandlers from the outside:

Toolbar toolbar = new Toolbar();
toolbar.setForwardHandler(new ActionHandler() {
  void perform() {
    doIt();
  }
});

The reason why I'm not using interfaces like ForwardHandler, and CancelHandler is, that I want to pass the handler to a toolbar, what takes ActionHandlers as parameters. Or would you pass the entire page to the toolbar and let the toolbar decide what buttons to display depending on the implemented interfaces? Sounds like bad OOP to me.

The idea is that not every page has to define a new toolbar, but maybe it would be simpler ...

+1  A: 

Why not use a protected field? It would work; subclasses would simply reassign the field to the ActionHandler they desire.

However I think this is worse than a protected method. You are attempting to define behavior, and behavior is defined by methods. With a field, you either assign its initial value to null or some dummy handler, which leaves the object in a weird state, where behavior that should be intrinsically defined by the object can be accidentally left undefined.

Since a protected method really isn't more complex or more code, I think it's appropriate. It can have a default implementation which does nothing.

I don't know if it makes sense for concrete subclasses to have their behavior defined by a caller. If FooPage really represents page Foo, and Foo has a fixed behavior, then FooPage ought to define it.

I don't know if there are bad side effects, but, passing something like the page entity to an object to let it decide its behavior does not sound terrible in principle.

Sean Owen
If I would use a "default implementation which does nothing", I had to look via reflections what methods are overridden, to display only the buttons with real actions.
deamon