Monday, January 15, 2007

Strategy Pattern vs Visitor Pattern

I have been trying to memorise Gang of Four design patterns recently, and came across the Strategy and Visitor patterns.

I struggled for a while to understand the difference between these two patterns, and the circumstances that would require one over the other.

I believe I understand correctly now, and thought it prudent to write it down somewhere. Here is as good a place as any for me to refer back to later, and it provides the added bonus of allowing people to correct me.

This post may not give you a good introduction into the Visitor and Strategy patterns, but will hopefully clarify when you should use one over the other (something I had difficulty finding a nice example of on the web).

Firstly allow me to provide an overview in my own words for each of the patterns:

Visitor Pattern
Consists of "Visitees" or "Hosts" and "Visitors". Hosts are objects within an object tree, and Visitors contain operations to be performed on these Hosts.

Hosts expose an Accept() method, which takes a Visitor object, and Visitors expose a Visit() method which has an overload for each Host. When the Accept() method is called on the Host, and a Visitor passed, a Visit() method is called on the visitor.

Using this pattern, operations become Double Dispatch, meaning they are executed based on two classes; the Host and the Visitor.

Strategy Pattern
Consists of a "Context" and a "Strategy". Contexts are objects within a tree related classes, and a Strategy is a class containing a series of operations to be used by the Contexts.

Strategy provides an interface of which Context objects are aware. When a Context object is created, a Strategy is also created (if not static) and given to the Context. Operations can then be selected from the selected Strategy as desired.

The Difference
While both patterns improve separation of concerns, and are fairly similar at face value, there are some important differences:

The Strategy pattern is designed to have the Strategy operation decided at runtime. Concrete Strategy objects can be passed to each Context operation. According to the Gang of Four Design Patterns book, Visitor patterns have a Composite Association between the Host and the Visitor and therefore the Visitor containing the operations has the same life cycle as the Host.

The Visitor in the Visitor Pattern must be aware of all Hosts and provide operations for each. The Visitor controls the operations run by the Host. This means that if your object model changes regularly, it will involve additional maintenance if a Visitor Pattern is used.

The Strategy in the Strategy Pattern will provide only the required algorithms, and the decision over which operation is executed is handled by the Context. Therefore the Context in the Strategy Pattern must be aware of the operations on the Strategy. If a Context is added, there is less maintenance (providing a new algorithm is not required).

Use the Visitor Pattern When:
  • An object structure will not change often, but operations across them will.
  • You have specific related functionality for each concrete class, and wish to encapsulate it.
  • Operation requires data that the Object shouldn't know about.
  • You wish to maintain state within operations across multiple objects.
Example:
  • An application may change its "Skin" which will alter the way controls are drawn. The code for deciding how controls are drawn could be encapsulated in Visitor implementations. Each control will require a separate operation.

Use the Strategy Pattern When:
  • A few algorithms will be used by many different classes.
  • Different algorithms may be used by a class at different times.
  • Operation requires data that the Object shouldn't know about.
  • Classes are using multiple conditional statements. These can be moved to an implementation of the Strategy class.
  • An object structure is likely to change often.
Example:
  • Different methods of calculating interest and fees will be used by clients of a bank. These algorithms can be encapsulated in Strategy implementations and associated with individual clients at runtime.

I am interested in getting feedback on these conclusions. Please let me know if you think anything I have written in incorrect, or you can think of better examples or ways to clarify things.

2 Comments:

Blogger Leedrick said...

Thanks for your input Paul. I agree with your comment on the contexts not needing to be part of a hierarchy, and I have changed the text to read "contexts are related classes".

An important point you raised is that the key to understanding the difference between these patterns (GOF calls Visitor and Strategy behavioural, unlike the Bridge pattern which it calls structural) is to see how they adapt to change. This reveals the biggest differences between these two patterns.

The fact that a missing operation specific to a new "Visitee" will be determined at compile time is also and important point. That said, I don't think it is something that will help you decide which pattern to use. It's more of a nice side effect.

I agree with Scott Meyers that Visitor is not a great name for the pattern. I can't come up with a better one right now though:)

Right now I have the G.O.F. Design Patterns book, and the power of the Internets for reference. Some more good examples of the usage of the various patterns would be nice, but I'd probably look for c# based examples. I can read c++, but I certainly wouldn't call myself an experienced user.

4:24 PM  
Blogger Thang said...

I think visitor and strategy patterns are to solve different problems.

1) Strategy pattern works under a context while visitor pattern doesn't need a context to execute its methods. Context object is a very important key point when using Strategy pattern. Remember that client executes Strategy through method execute() of a context it has. The context abstracts away which strategy is executed from client perspective. Context class makes the model become many-many relationship. Same strategy can be used in different contexts and different contexts can be used the same strategy.

2) Visitor pattern must know visitee's interface and what kind of data it expects from visitee. Strategy doesn't need to understand any interface. Strategy can potentially access many resources from different places to perform its execution. In this way, Strategy pattern deals with a larger scope than visitor pattern does.

3:27 PM  

Post a Comment

<< Home