none
difficulty in understanding visitor pattern RRS feed

  • Question

  • Hi All,
    I have confusion on why is Visitor pattern is needed.One 
    of the famous website provides the following code to explain the
    use of visitor pattern,but it is nto understood by me.
    Can somebody please explin in simple terms what is visitor pattern
    and in what case it is implemented.
     
     
    package Transactions;
    
    public class Transaction
    {
      public abstract void accept(TransactionVisitor v);
    }
    
    interface TransactionVisitor
    {
      public void visit(DepositTransaction dt);
      public void visit(WithdrawlTransaction wt);
    }
    
    class DepositTransaction extends Transaction
    {
      public void accept(TransactionVisitor v)
      {v.visit(this);}
    }
    
    class WithdrawlTransaction extends Transaction
    {
      public void accept(TransactionVisitor v)
      {v.visit(this);}
    }
    
    class TransactionUIFactory implements TransactionVisitor
    {
      private UI itsUI;
      public UI getUI() {return itsUI;}
      public void visit(DepositTransaction dt) {
        itsUI = new DepositUI(dt);
      }
      public void visit(WithdrawlTransaction wt) {
        itsUI = new WithdrawlUI(wt);
      }
    }
     
    Regards
    Tuesday, September 12, 2006 12:14 PM

Answers

  • A visitor pattern is one form of double dispatch. It arises when you have a family of objects and you want to perform an common operation on them, but the operation differs based on the type. The operation is being done by another object and so polymorphism is not applicable.

    In the example you cite, you have a family of transaction types, with two listed: deposit and withdrawl. The example does not fully articulate these classes, but we can assume that they would contain the data and methods necessary for their respective type of transaction. The visitor class they have shown does not seem to have a purpose, but suppose the application called for end of day processing the included verifying and balancing all transactions. The logic for verification could be very complex and vary based on the type of transaction. Furthermore, the verification needed depends on the operation, in this case end of day, but there might be other operations like end of month. Therefore, the implementation has two methods Verify(DepositTransaction) and Verify(WithdrawlTransaction) on the EndOfDay class.

    To do the EndOfDay processing you would have a collection of Transactions that was a mix of all types. One implementation could be:

    foreach( Transaction t in AllTransactions )

    {

       if( t is WithdrawlTransaction )

              Verify( (WithdrawlTransaction) t )

       else if ( t is DepositTransaction )

             Verify( (DepositTransaction) t )

    }

     

    Using the Visitor pattern, the transaction objects accept visitors and the cast is done implicitly. Now the code becomes:

    foreach( Transaction t in AllTransactions )

            accept( this ); // this is the EndOfDay object

    The verify logic would be in the appropriate Visit() methods.

     

    A big key to the use of the Visitor pattern is that the code to be executed is external to the family of objects. It needs to be something that is done based on their data or methods, but does not belong in the classes themselves because it is more external to them or can change based on circumstances.

     

    I find that the more general problem of double dispatch arises more than a true Visitor scenario. In that case, there is more coupling between the class operating on the family and the family of objects.

    I find the transaction example lacking, somewhat, but hope this will point you in the right direction.

    Tuesday, September 12, 2006 3:23 PM

All replies

  • A visitor pattern is one form of double dispatch. It arises when you have a family of objects and you want to perform an common operation on them, but the operation differs based on the type. The operation is being done by another object and so polymorphism is not applicable.

    In the example you cite, you have a family of transaction types, with two listed: deposit and withdrawl. The example does not fully articulate these classes, but we can assume that they would contain the data and methods necessary for their respective type of transaction. The visitor class they have shown does not seem to have a purpose, but suppose the application called for end of day processing the included verifying and balancing all transactions. The logic for verification could be very complex and vary based on the type of transaction. Furthermore, the verification needed depends on the operation, in this case end of day, but there might be other operations like end of month. Therefore, the implementation has two methods Verify(DepositTransaction) and Verify(WithdrawlTransaction) on the EndOfDay class.

    To do the EndOfDay processing you would have a collection of Transactions that was a mix of all types. One implementation could be:

    foreach( Transaction t in AllTransactions )

    {

       if( t is WithdrawlTransaction )

              Verify( (WithdrawlTransaction) t )

       else if ( t is DepositTransaction )

             Verify( (DepositTransaction) t )

    }

     

    Using the Visitor pattern, the transaction objects accept visitors and the cast is done implicitly. Now the code becomes:

    foreach( Transaction t in AllTransactions )

            accept( this ); // this is the EndOfDay object

    The verify logic would be in the appropriate Visit() methods.

     

    A big key to the use of the Visitor pattern is that the code to be executed is external to the family of objects. It needs to be something that is done based on their data or methods, but does not belong in the classes themselves because it is more external to them or can change based on circumstances.

     

    I find that the more general problem of double dispatch arises more than a true Visitor scenario. In that case, there is more coupling between the class operating on the family and the family of objects.

    I find the transaction example lacking, somewhat, but hope this will point you in the right direction.

    Tuesday, September 12, 2006 3:23 PM
  • Sunday, February 11, 2007 6:01 PM