tags:

views:

16

answers:

1

I have an interface FooModel and a class DefaultFooModel that have a few simple properties. I am getting stuck on a boolean enable property because I want to have this be vetoable/deferred:

public interface FooModel {
   public boolean isEnabled();
   /** returns old value */
   public boolean setEnable(boolean enable); 

   public void addFooListener(FooModel.Listener listener);
   public void removeFooListener(FooModel.Listener listener);

   public interface Listener {
      public void onFooEnableUpdate(boolean newEnable, boolean oldEnable);
   }
}

What I want is for the model M to be the central point of access for the enable property. But here's the sequence of events that I want to occur:

  1. view V (or any user of the model M) calls FooModel.setEnable(enable) on an arbitrary thread.
  2. FooModel may either:

    a. immediately call onFooEnableUpdate(newEnable, oldEnable) on each of its listeners in arbitrary order

    b. start a potentially long sequence of events whereby another entity (e.g. controller C) can decide whether to enable, and somehow let FooModel know, whereby the enable property may be updated and then we proceed as usual in (a) above.

The thing is, I'm not sure how to go about doing this.

Approach 1: the mechanism to do this shouldn't be part of the model's interface. Instead, my DefaultFooModel has an implementation which accepts a FooController:

public interface FooController {
   public void onFooEnableRequest(boolean newEnable, boolean oldEnable);
}

When DefaultFooModel.setEnable() is called, it then calls FooController.onFooEnableRequest(). The controller is expected to return immediately, but can take its time to digest the request, and then later call DefaultFooModel.updateEnable() which causes the real onFooEnableUpdate() to get called.

Approach 2: build something into the FooModel interface, but I'm not sure what.

Approach 3: Don't build anything into FooModel, just have it handle a regular property. Instead have the Controller listen to FooModel.onFooEnableUpdate() and override setEnable right away to the old value, then call FooModel.setEnable() later to set the new value.

Any advice?

A: 

Make FooModel a class instead of an interface.

The problem I see with making FooModel an interface is the complex logic that needs to be coded into the listener mechanism. It's generally not a good idea to force anyone who implements the interface to have to implement the listener logic as well.

Instead, make FooModel a class, implement the listener interface yourself, and creatively create public methods that can be overridden where you need to implement more specific functionality.

  • notifyListeners(boolean newEnable, boolean oldEnable) notifies all listeners, by default by calling the following method, but could be overridden to do nothing, or to notify conditionally
  • notifyListener(Listener listener, boolean newEnable, boolean oldEnable) notifies a specific listener
Erick Robertson