В настоящее время я изучаю Шаблон посетителя и пробую различные идеи.Ниже у меня есть код моей текущей настройки, который я хотел бы получить как-нибудь.
Я хотел бы иметь двух посетителей, один, который подсчитывает экземпляры Red
и Blu
отдельно, а другой, который считаетчто угодно (можно предположить, что это Color
)
Это, конечно, можно решить, просто внедрив второго посетителя аналогично первому, но не используя отдельные переменные для подсчета, а только одну.Однако я думаю, что в этом нет необходимости - если бы у меня было, например, много разных цветов, код был бы очень повторяющимся: все функции в этом посетителе были бы одинаковыми, они просто увеличивали бы одну переменную.Конечно, есть более простой способ, но как?Согласно стандартному шаблону посетителя, я должен реализовать для каждого цветового класса функции посещения, таким образом, это не совсем правильный подход.
Как бы кто-нибудь решил эту проблему?
#include <iostream>
class Color
{
public:
virtual void accept(class Visitor*) = 0;
};
class Red: public Color
{
public:
/*virtual*/
void accept(Visitor*);
void eye()
{
std::cout << "Red::eye\n";
}
};
class Blu: public Color
{
public:
/*virtual*/
void accept(Visitor*);
void sky()
{
std::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()
{
std::cout << "Reds " << m_num_red << ", Blus " << m_num_blu << '\n';
}
private:
int m_num_red, m_num_blu;
};
class TemplateVisitor: public Visitor
{
public:
TemplateVisitor() : num_of_colours(0) {}
/*virtual*/
template<class C>
void visit(C* c)
{
++num_of_colours;
}
void report_num()
{
std::cout << "Colours " << num_of_colours << '\n';
}
private:
int num_of_colours;
};
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, nullptr
};
CountVisitor count_operation;
TemplateVisitor template_visitor;
for (int i = 0; set[i]; i++)
{
set[i]->accept(&count_operation);
set[i]->accept(&template_visitor);
}
count_operation.report_num();
template_visitor.report_num();
}