// Purpose.  Visitor design pattern

// 1. Add an accept(Visitor) method to the "element" hierarchy
// 2. Create a "visitor" base class w/ a visit() method for every "element" type
// 3. Create a "visitor" derived class for each "operation" to do on "elements"
// 4. Client creates "visitor" objects and passes each to accept() calls

interface Element {
   public void accept( Visitor v ); // first dispatch     // 1. accept(Visitor)
}                                                         //    interface

class This implements Element {
   public void   accept( Visitor v ) { v.visit( this ); } // 1. accept(Visitor)
   public String thiss()             { return "This"; }   //    implementation
}

class That implements Element {
   public void   accept( Visitor v ) { v.visit( this ); }
   public String that()              { return "That"; }
}

class TheOther implements Element {
   public void   accept( Visitor v ) { v.visit( this ); }
   public String theOther()          { return "TheOther"; }
}

interface Visitor {                                    // 2. Create a "visitor"
   public void visit( This e ); ////// second dispatch //    base class with a
   public void visit( That e );                        //    visit() method for
   public void visit( TheOther e );                    //    every "element"
}                                                      //    type

class UpVisitor implements Visitor {                   // 3. Create a "visitor"
   public void visit( This e ) {                       //    derived class for
      System.out.println( "do Up on " + e.thiss() ); } //    each "operation"
   public void visit( That e ) {                       //    to perform on
      System.out.println( "do Up on " + e.that() ); }  //    "elements"
   public void visit( TheOther e ) {
      System.out.println( "do Up on " + e.theOther() ); }
}

class DownVisitor implements Visitor {
   public void visit( This e ) {
      System.out.println( "do Down on " + e.thiss() ); }
   public void visit( That e ) {
      System.out.println( "do Down on " + e.that() ); }
   public void visit( TheOther e ) {
      System.out.println( "do Down on " + e.theOther() ); }
}

class VisitorDemo {
   public static Element[] list = { new This(), new That(), new TheOther() };
   public static void main( String[] args ) {
      UpVisitor    up   = new UpVisitor();             // 4. Client creates
      DownVisitor  down = new DownVisitor();           //    "visitor" objects
      for (int i=0; i < list.length; i++)              //    and passes each
         list[i].accept( up );                         //    to accept() calls
      for (int i=0; i < list.length; i++)
         list[i].accept( down );
}  }

// do Up on This                // do Down on This
// do Up on That                // do Down on That
// do Up on TheOther            // do Down on TheOther

