Java Q&A
by Eric J. Bruno

Listing One
public class QuoteSource 
{
    protected Vector listeners;
    public QuoteSource() 
    {
    }

    public void addListener(Object listenerObj)
    {
        listeners.add( listenerObj );
    }

    public void synchronized fire_quoteChange(double newQuote)
    {
        QuoteEvent qe = new QuoteEvent( this, newQuote );

        // give each listener in the Vector 
        // this QuoteEvent object

        Vector listenersCopy;
        synchronized ( this )
        {
            listenersCopy = (Vector)listeners.clone();
        }
        
        int cnt = listenersCopy.size();
        for (int i = 0; i < cnt; i++)
        {
            QuoteChangedListener client = 
                (QuoteChangedListener)listenersCopy.elementAt(i);

            client.quoteChanged( qe );
        }
    }
}

public class QuoteListener implements QuoteChangedListener
{
    protected QuoteSource quoteSource;
    public QuoteListener() 
    {
        quoteSource = new QuoteSource();
        quoteSource.addListener( this );
    }

    public void quoteChanged(QuoteEvent qe)    
    {
        // do something with the new quote
        ...
    }
}
Listing Two
public synchronized boolean regSource(Object sourceObj, String eventName)
{
   // sourceObj must implement SourceInterface
   if ( ! ( sourceObj instanceof SourceInterface ) )
      return false;
   // Add this source object to our HashMap once only 
   if ( sourceObjects.containsKey( eventName ) == true )
      return false;
   sourceObjects.put( eventName, sourceObj );
   // Since listener and source objects can register at any time
   // check if there are matching listener objects in the Vector
   int i = 0;
   int count = listenerObjects.size();
   while ( i < count )
   {
      EventComponent listener = (EventComponent)listenerObjects.elementAt(i);
      // Check the listener's event interface name
      if ( eventName.equals( listener.getEventName() ) )
      {
         notifySource( sourceObj, listener.getObject() );
         // Remove the listener. All remaining elements will 
         // shift left so don't increment vector index i
         listenerObjects.remove( i );
         count--; // one less item in the list now
      }
      else
      {
         i++; // Check the next listener
      }
   }
  return true;
}
Listing Three
public synchronized boolean regListener(Object listenerObj, String eventName)
{
   // Search for the Matching Source in the HashMap
   EventComponent source = (EventComponent)sourceObjects.get( eventName );
   if ( source != null )
   {
      notifySource( source.getObject(), listenerObj );
   }
   else
   {
      // Didn't find the matching Source. Add the listener to the
      // list in anticipation that the source will register later
      EventComponent listener = new EventComponent( listenerObj, eventName );
      listenerObjects.addElement( listener );
   } 
   return true;
} 
Listing Four
class EventComponent
{
    protected Object theObject = null;
    protected String eventType = null;
    public EventComponent(Object obj, String s)
    {
        theObject = obj;
        eventType = s;
    }
    public Object getObject()
    {
        return theObject;
    }
    public String getEventType()
    {
        return eventType;
    }
}
Listing Five
public interface QuoteChangedListener extends java.util.EventListener 
{
    public static final String eventName = "QuoteChangedListener";

    // called when the stock quote changes
    public void quoteChanged(QuoteEvent qe);
}

public class QuoteSource implements SourceInterface
{
    protected Vector listeners;
    protected EventAgent eventAgent = EventAgent.getInstance();

    public QuoteSource() 
    {
        eventAgent.regSource( this, QuoteChangedListener.eventName);
    }

    public void addListener(Object listenerObj)
    {
        listeners.add( listenerObj );
    }

    public void fire_quoteChange(double newQuote)
    {
        ...
    }
}
Listing Six
public class QuoteListener implements QuoteChangedListener
{
    // NOTE: no longer need to know the source component
    // OBSOLETE: protected QuoteSource quoteSource;

    protected EventAgent eventAgent = EventAgent.getInstance();

    public QuoteListener() 
    {
        eventAgent.regListener( this, QuoteChangedListener.eventName );
        
        // OBSOLETE: quoteSource = new QuoteSource();
        // OBSOLETE: quoteSource.addListener( this );
    }

    public void quoteChanged(QuoteEvent qe)    
    {
        ...
    }
}








