[otj-users] Using ObserverPattern

Miguel Pessoa Monteiro mmonteiro at di.fct.unl.pt
Wed Jul 9 21:57:17 CEST 2008


Hello,

I've been trying to use the reusable implementation of Observer, which gave rise to
several questions. I used an example by an independent author (seems a good way to
expose issues and hurdles). Class Flower is a subject, Bee and Hummingbird are
observers.

Question 1:
I would like to to map subject objects to observer objects dynamically, which means
using role method addObserver. Unfortunately, the example on the OT/J site does not
use this and other methods. It is not clear how can they to be used. I experimented
several variants, but some compiler error always gets in the way. So, how do I call
addObserver from main? My original intention was to pass base objects as arguments:
instances of classes Bee and Hummingbird, which play the Subject role.

Question 2:
It seems that playedBy cannot be used to bind more than one base class to a role. To
circumvent, I resorted to two subclasses of role Observer: BeeObserver and
HummingbirdObserver. Would this be the recommended way to bind more than one class
to a role?

Question 3:
At some point, I tried to encapsulate the role methods with team methods, the way
Stephan suggested in an old post (2005 Sep 7 - "role object creation considered
complex?"). However, the parameter declaration 'Base as Role param' does not seem to
be polymorphic, which forced me to duplicate encapsulating methods (mapSubject2Bee
and mapSubject2Hummingbird). Surely there is a better way, but how?

Question 4:
I get compiler error "A non-abstract role method exists for this callout-binding.
Use callout-override ('=>')". This error puzzles me, as update is declared abstract
in the role. What is the the cause?


Thanks in advance,
mpm

----------------------------------------------------------------------
//Base class to play the "Subject" role
public class Flower {
   private boolean isOpen;

   public Flower() {
      isOpen = false;
   }
   // Opens its petals
   public void open() {
      isOpen = true;
      System.out.println("open");
   }
   //Closes its petals
   public void close() {
      isOpen = false;
      System.out.println("close");
   }
}
----------------------------------------------------------------------
//Base class to play the "Observer" role
public class Bee {
   private String _name;

   public Bee(String name) {
      _name = name;
   }
   //Reaction to Flower.open
   public void haveBreakfast() {
      System.out.println("Bee " + _name + "'s breakfast time!");
   }
   //Reaction to Flower.close
   public void goToBed() {
      System.out.println("Bee " + _name + "'s bed time!");
   }
}
----------------------------------------------------------------------
//Another "Observer" base class; similar to Bee, though type-unrelated
//and with a different interface.
public class Hummingbird {
   private String _name;

   public Hummingbird(String name) {
      _name = name;
   }
   //Reaction to Flower.open
   public void breakfastTime() {
      System.out.println("Hummingbird " + _name + "'s time to have breakfast!");
   }
   //Reaction to Flower.close
   public void bedTime() {
      System.out.println("Hummingbird " + _name + " goes to sleep!");
   }
}
----------------------------------------------------------------------
public team class ObservingOpen extends ObserverPattern {

   public void mapSubject2Bee(Flower as Subject subject, Bee as Observer observer) {
      subject.addObserver(observer);
   }

   public void mapSubject2Hummingbird(Flower as Subject subject, Hummingbird as
Observer observer) {
      subject.addObserver(observer);
   }

   public class Subject playedBy Flower {
           changeOp <- after open;
       }
   public class BeeObserver extends Observer playedBy Bee {
      update -> haveBreakfast;
   }
   public class HummingbirdObserver extends Observer playedBy Hummingbird {
      update -> breakfastTime;
   }
}

----------------------------------------------------------------------
//Driver for the example
public class Main {
   public static void main(String[] args) {
      /*final*/ ObservingOpen observationRelationship = new ObservingOpen();
      observationRelationship.activate();

      Flower flower = new Flower();

      Bee beeA = new Bee("A");
      Bee beeB = new Bee("B");
      observationRelationship.mapSubject2Bee(flower, beeA);
      observationRelationship.mapSubject2Bee(flower, beeB);

      Hummingbird ha = new Hummingbird("A"), hb = new Hummingbird("B");
      observationRelationship.mapSubject2Hummingbird(flower, ha);

      // A change that interests observers:
      flower.open();
      flower.close();
      observationRelationship.deactivate();
      System.out.println("\nterminated.");
   }
}
----------------------------------------------------------------------

-- 
Miguel P. Monteiro          | cell phone +351 96 700 35 45
Departamento de Informatica | Phone +351 21 294 8536 ext. 10708
Faculdade Ciencias e Tecnol.| Fax: +351 21 294 8541
Universidade Nova de Lisboa | URL: http://ctp.di.fct.unl.pt/~mpm
2829-516 Caparica, PORTUGAL | e-mail: mmonteiro [at] di fct unl pt




More information about the otj-users mailing list