import java.util.ArrayList;

interface Observer
{
    void update( Subject observee );
    void destroy( );
}

abstract class Subject
{
    public void addObserver( Observer obs )
    { 
        observers.add( obs );
    }

    public void removeObserver( Observer obs )
    {
        observers.remove( obs );
    }

    public void notifyObservers( )
    {
        for( int i = 0; i < observers.size( ); i++ )
            ( (Observer) observers.get( i ) ).update( this );
    }

    ArrayList observers = new ArrayList( );
}


// Timer class: tick method calls notify.
class Timer extends Subject
{
    public void tick( )
    {
        notifyObservers( );
    }
}

// EchoObserver class: this in an observer.
// It is constructed with a Timer object; when
// the Timer object ticks, update is
// automatically called.
class EchoObserver implements Observer
{
    public EchoObserver( int id, Timer t )  
    {
        myId = id;
        observee = t;
        observee.addObserver( this );
    }

    public void destroy( )
    {
        observee.removeObserver( this );
    }

    public void update( Subject s )
    {
        if( observee == s )
            System.out.println( myId );
    }

    private int myId;
    private Subject observee;
}

public class ObserverDemo
{
    private static void testEcho12( Timer t )
    {
        EchoObserver e1 = new EchoObserver( 1, t );
        EchoObserver e2 = new EchoObserver( 2, t );

        System.out.println( "Expecting 1 and 2 to respond." );
        t.tick( );
        System.out.println( "1 and 2 disappear." );
        e1.destroy( );
        e2.destroy( );
    }

    public static void main( String [ ] args )
    {
        Timer t = new Timer( );
        Timer other = new Timer( );

        testEcho12( t );   // 1 and 2 should respond

        EchoObserver e3 = new EchoObserver( 3, t );
        EchoObserver e4 = new EchoObserver( 4, t );
        EchoObserver e5 = new EchoObserver( 5, other );  // registered with other, not t

        System.out.println( "Only 3 and 4 are currently observable." );
        System.out.println( "Expecting 3 and 4 to respond." );
        t.tick( );
    }
}
