Visitor - shoonie/StudyingDesignPattern GitHub Wiki

Intent

Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.

Diagram

disgram

Consequences

  1. Visitor makes adding new operations easy.
  2. A visitor gathers related operations and separates unrelated ones.
  3. Adding new ConcreteElement classes is hard.
  4. Visiting across class hierarchies.
  5. Accumulating state.
  6. Breaking encapsulation.

Implementation

  1. Double dispatch. Effectively, the Visitor pattern lets you add operations to classes without changing them. Visitor achieves this by using technique called Double-Dispatch
  2. Who is responsible for traversing the object structure?

Sample Code

#include <iostream>
using namespace std;
class Color
{
public:
	virtual void accept(class Visitor*) = 0;
};

class Red : public Color
{
public:
	/*virtual*/void accept(Visitor*);
	void eye()
	{
		cout << "Red::eye\n";
	}
};
class Blu : public Color
{
public:
	/*virtual*/void accept(Visitor*);
	void sky()
	{
		cout << "Blu::sky\n";
	}
};

class Visitor
{
public:
	virtual void visit(Red*) = 0;
	virtual void visit(Blu*) = 0;
};

class CountVisitor : public Visitor
{
public:
	CountVisitor()
	{
		m_num_red = m_num_blu = 0;
	}
	/*virtual*/void visit(Red*)
	{
		++m_num_red;
	}
	/*virtual*/void visit(Blu*)
	{
		++m_num_blu;
	}
	void report_num()
	{
		cout << "Reds " << m_num_red << ", Blus " << m_num_blu << '\n';
	}
private:
	int m_num_red, m_num_blu;
};

class CallVisitor : public Visitor
{
public:
	/*virtual*/void visit(Red *r)
	{
		r->eye();
	}
	/*virtual*/void visit(Blu *b)
	{
		b->sky();
	}
};

void Red::accept(Visitor *v)
{
	v->visit(this);
}

void Blu::accept(Visitor *v)
{
	v->visit(this);
}

int main()
{
	Color *set[] =
	{
		new Red, new Blu, new Blu, new Red, new Red, 0
	};
	CountVisitor count_operation;
	CallVisitor call_operation;
	for (int i = 0; set[i]; i++)
	{
		set[i]->accept(&count_operation);
		set[i]->accept(&call_operation);
	}
	count_operation.report_num();
}
⚠️ **GitHub.com Fallback** ⚠️