Saturday, September 5, 2009

Double Dispatch and Visitor Pattern

Double dispatch is a way to call different (but-related) concrete functions depending on the runtime types of the various objects involved in the call. IT basically replacing static compile time casting with dynamic resolving of calls.

Here is an example of the a double dispatch. Let's say it's a game. You have a wildanimal that attacks types of humans, and a warrior which derives from human. Let us consider a wildanimal attacking a warrior. I strongly suggest running this code for a better understanding.

The problem is on line 51 you have w->attack(h). This leads to static compile time function overloading and you end up selecting the 'Human Attack' at line 35. This leads to a wild animal attacking a human despite the fact that it should be attacking a warrior.

The solution is to have a DD that allows the proper dynamic cast by using the 'this' pointer (line 28).  Now when you call h->attackedbywildanimal(w); at line 54 you will get the correct wild animal attacking a warrior instead of a human.

Note that a simpler but far less flexible solution would have been to simply statically cast the pointer at line 51 to be w->attack((warrior*)h);.

Note that to have all the code in a single file I needed class definitions at the top and the wildanimal implementation is actuall at the bottom. Remind me to use java next time!

1. #include <iostream>
 2. 
 3. using namespace std;
 4. 
 5. 
 6. class human;
 7. class warrior;
 8. class wildanimal{
 9. public:
10.     void attack(human*);
11.     void attack(warrior*);
12. };
13. 
14. 
15. class human{
16.   public:
17.     virtual void attackedbywildanimal(wildanimal *animal){
18.         animal->attack(this);
19.     }
20.     void GetHealth(){
21.         cout<<"Human health\n";
22.     }
23. };
24. 
25. class warrior : public human{
26. public:
27.     virtual void attackedbywildanimal(wildanimal *animal){
28.         animal->attack(this);
29.     }
30.     void GetHealth(){
31.         cout<<"Warrior health\n";
32.     }
33. };
34. 
35. void wildanimal::attack(human* h){
36.       cout<<"Animal attacks human ";
37.       h->GetHealth();
38. }
39. void wildanimal::attack(warrior* w){
40.       cout<<"Animal attacks warrior ";
41.       w->GetHealth();
42. }
43. 
44. int main(int argv, char** argc){
45. 
46.   
47.     human * h = new warrior();
48.     wildanimal * w = new wildanimal();
49.   
50.     //Problem
51.     w->attack(h);
52.     
53.     //Double Dispatch solution
54.     h->attackedbywildanimal(w);
55. }
Hide line numbers

C++ Java Core Programming Design Paterns

Design pattern periodic table. The Gang Of four (GoF) design patterns consist of the fundamental creational, structural and behavioural patterns that form the basis for all other patterns. Are these in fact fundamental? Can they be refactored? Let us explore this topic to better understand desgin patterns and their use in everyday programming.

GoF's original books was "Design Patterns: Elements of Reusable Object-Oriented Software" by ErichGamma, RichardHelm, RalphJohnson and John Vlissides.


Creational PatternsStructural PatternsBehavioural Patterns

FM
Factory Method
Px
Proxy
B
Bridge
AF
Abstract Factory
Pt
Prototype
Tm
Template
Cd
Command
Md
Mediator
O
Observer
In
Interpreter
CR
Chain of responsibility
A
Adapter
Fy
Flyweight
Bu
Builder
S
Singleton
Sr
Strategy
Mm
Memento
St
State
It
Iterator
V
Visitor
Cp
Composite
D
Decorator
Fc
Facade