pgnatyuk
asked on
Visitor pattern
Hi
I have a question about the visitor pattern. Here is an example from evilrix:
Simple and nice.
Probably, I do not understand the pattern well. Now without the pattern implemented I have 7 methods like foo(CItem*). In each method I call item->GetType() and then have a switch statement.
So I will have 1 visitor and 7 accept and 7 visit functions?
I have a question about the visitor pattern. Here is an example from evilrix:
#include <iostream>
struct CItem1;
struct CItem2;
struct CItem3;
struct Visitor
{
void visit(CItem1 * p);
void visit(CItem2 * p);
void visit(CItem3 * p);
};
struct CItem
{
virtual void accept(Visitor * p) = 0;
};
struct CItem1 : CItem
{
void accept(Visitor * p)
{
p->visit(this);
}
void hello1()
{
std::cout << "hello from CItem1" << std::endl;
}
};
struct CItem2 : CItem
{
void accept(Visitor * p)
{
p->visit(this);
}
void hello2()
{
std::cout << "hello from CItem2" << std::endl;
}
};
struct CItem3 : CItem
{
void accept(Visitor * p)
{
p->visit(this);
}
void hello3()
{
std::cout << "hello from CItem3" << std::endl;
}
};
void Visitor::visit(CItem1 * p)
{
p->hello1();
}
void Visitor::visit(CItem2 * p)
{
p->hello2();
}
void Visitor::visit(CItem3 * p)
{
p->hello3();
}
void foo(CItem * p)
{
Visitor v;
p->accept(&v);
}
int main()
{
CItem1 i1;
CItem3 i2;
CItem3 i3;
foo(&i1);
foo(&i2);
foo(&i3);
};
Simple and nice.
Probably, I do not understand the pattern well. Now without the pattern implemented I have 7 methods like foo(CItem*). In each method I call item->GetType() and then have a switch statement.
So I will have 1 visitor and 7 accept and 7 visit functions?
I will look at this in a little bit.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thanks.
I didn't get the part about " you have resolved from a dynamic to a static type". Why you use these terms "static" and "dynamic"? How it's related to the visitor pattern?
From your answer I already can implement the pattern in my program.
I didn't get the part about " you have resolved from a dynamic to a static type". Why you use these terms "static" and "dynamic"? How it's related to the visitor pattern?
From your answer I already can implement the pattern in my program.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
In acyclic visitor you would need one set of accept/visit for every new class, plus for aggregate visitors like AllVisitor, those must be changed too. In my sample, I added default implementations to Item1Visitor etc., but you can keept those are empty abstract methods if you wish like
struct Item2Visitor : Visitor {
virtual void visit(CItem2 * p) =0;
};
The biggest advantage is the decoupling achieved.
struct Item2Visitor : Visitor {
virtual void visit(CItem2 * p) =0;
};
The biggest advantage is the decoupling achieved.
>> I didn't get the part about " you have resolved from a dynamic to a static type".
>> Why you use these terms "static" and "dynamic"? How it's related to the visitor pattern?
See code below to define difference between dynamic and static type and how this relates to the visitor pattern.
>> Why you use these terms "static" and "dynamic"? How it's related to the visitor pattern?
See code below to define difference between dynamic and static type and how this relates to the visitor pattern.
struct CItem { virtual ~CItem(){} };
struct CItemEx : CItem{}
foo(CItem* dynamic_type)
{
// The static type might be CItem or CItemEx but we don't know without either
// a discriminator or dynamic_cast but visitor pattern can resolve this for us
// Let the visitor pattern handle it, dynamic casts are slow and discriminators
// are ugly and not very OO like, the C++ type system can resolve this for us.
hello(dynamic_type);
goodbye(dynamic_type);
}
CItemEx itemEx
foo(&itemEx);
ASKER
Thanks, evilrix. I think, that's what I need.
ambience, I think, here is a mistake:
void accept(Visitor * p) {
Item2Visitor* visitor = dynamic_cast(p);
if(visitor) p->visit(visitor);
}
Anyway, thank you.
ambience, I think, here is a mistake:
void accept(Visitor * p) {
Item2Visitor* visitor = dynamic_cast(p);
if(visitor) p->visit(visitor);
}
Anyway, thank you.
int main()
{
CItem* array[3] = { 0 };
array[0] = new CItem1;
array[1] = new CItem2;
array[2] = new CItem3;
for (int i = 0; i < 3; ++i)
{
hello(array[i]);
goodbye(array[i]);
}
}
ASKER
Thank you.