Search code examples
javaeventsactionscriptobserver-pattern

Observer design -- how to access method.invoke scope?


i currently have a Java Observer/Observable setup in which i switch on some field within the Object parameter of Observer.update (e.g. event id) to determine how to handle an Observable notification.

this creates verbose code like:

public void update (Observable o, Object arg) {
    if (arg instanceof Event) {
        switch (((Event)arg).getID()) {
            case EVENT_TYPE_A:
                // do stuff...
                break;
            case EVENT_TYPE_B:
                // do stuff...
                break;
            case EVENT_TYPE_C:
                // do stuff...
                break;
        }
    }
}

coming from an ActionScript background, this feels unnecessarily verbose to me...instead of passing an instance of an Observer, i'd prefer to pass a callback method to be called directly by the Observable (more specifically, by a subclass). however, i'm not clear how to determine the object on which the method should be invoked (the class instance that 'owns' the method).

i could pass a reference to the instance enclosing the method, but this smells like bad OOP.

am i barking up the wrong tree? or is there a clean way to achieve this?


Solution

  • A cleaner implementation would involve removing the logic of whether the event can be handled by the observer/observable, to the actual observer/observable itself. It appears as if ActionScript has left you with a funny idea about the Observer pattern. Observe (no-pun-intended):

    public interface Observer{
    
      public void update( Event arg );
    }
    
    public class Event{
    
      public int ID;
    }
    
    public Button implements Observer{
    
      public void update ( Event arg ){
    
         switch (arg.ID){
    
           case 1:  //Buttonsy handle events of type 1
             //do something useful;
             break;
           default:
             System.out.println("Buttons don't handle events of ID: " + arg.ID);
             break;
         }
      }
    }
    
    public ProgressBar implements Observer{
    
      public void update ( Event arg ){
    
         switch (arg.ID){
    
           case 2: //ProgressBars handle events of type 2 and 3
             //do something useful;
             break;
           case 3:
             //do something else useful;
             break;
           default:
             System.out.println("Progress bars don't handle events of ID: " + arg.ID);
             break;
         }
      }
    }
    
    
    public class Subject{
    
     private ArrayList<Observer> allUIControls;
    
     public registerControl( Observer control ){
    
       allUIControls.add( control );
     }
    
     public void updateControls ( Event arg ) {
    
       foreach ( Observer control in allUIControls ){
    
         //pass the event to each UI control, and let the EVENT decide if it can understand the Event.ID
         //its not the job of Subject to decide if the Observer is fit to handle the event. THIS IS NOT THE OBSERVER pattern.
         control.update( arg );
       }
     }
    }