Creo que el nombre del visitante patrón es bastante desafortunado. En lugar de la palabra visitante, diría Functor u Operador y en lugar de 'visitar' diría 'aplicar'.
Mi comprensión del patrón de visitante es el siguiente:
En plantilla de meta-programación (STL/Boost) (compilar vinculante tiempo) se puede lograr (el diseño ortogonal) las separaciones de las operaciones de las estructuras, por el medio de objetos función (Functors.) Por ejemplo, en
template <class RandomAccessIterator, class Compare>
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
el borrador es un funtor/operador que representa 'menor que' la operación de una manera muy genérica, por lo que no tiene que tener muchas variantes de especie función:
Para patrón de visitante desea lograr algo similar, pero en el caso de encuadernación (tardía) de tiempo de ejecución:
Quiere simplificar la interfaz de A, desea mantener la posibilidad de futuras extensiones (las nuevas operaciones trabajan con A) y desea lograr la estabilidad de la interfaz de A en el caso de esas extensiones.
Desde el original 'grasa' de clase:
class A
{
public:
virtual void function_or_operation_1();//this can be implemented in terms of public interface of the other functions
virtual void function_or_operation_2();
//..etc
virtual void function_or_operation_N();
public:
//stable public interface, some functions of procedures
private:
//....
}
que eliminar el mayor número de función de interfaz pública como sea posible (siempre y cuando se pueden implementar en términos de las funciones no extraídos de la misma interfaz pública) y representan las operaciones como los objetos functor u objetos de una nueva jerarquía Functor:
se reduce el número de la función en la clase base a por tener interfaz muy genérico utilizando Functor_or_Operator hacia adelante declaró:
class Functor_or_Operator;
class A
{
public:
virtual void apply(Functor_or_Operator*);//some generic function operates on this objects from A hierarchy
//..etc
public:
//stable public interface, some functions
private:
//....
}
// Ahora tiene N (= 3) clases en una jerarquía (A, B, C) y M operaciones o funciones representadas por clases en la jerarquía Functor_or_Operator Debe implementar N * M definiciones de cómo cada la operación de Functor_or_Operator funciona en todas las clases en la jerarquía A. Lo importante es que puede hacerlo sin cambiar la interfaz de la clase 'A'. La declaración de la clase 'A' se vuelve muy estable en el caso de las nuevas incorporaciones al introducir nuevas operaciones o funciones que trabajan con objetos de una jerarquía o en el caso de nuevas clases derivadas en la jerarquía A. La estabilidad de A (sin cambios en A) en presencia de adiciones es importante para evitar la costosa (y algunas veces imposible) recompilación de software que incluye encabezados de A en muchos lugares.
Para cada clase nueva en la jerarquía A, extiende la definición de Functor_or_Operator base, agrega nuevos archivos de implementación, pero nunca necesita tocar el encabezado de la clase base A (generalmente clase de interfaz o abstracta).
class Functor_or_Operator
{
virtual void apply(A*)=0;
virtual void apply(B*)=0;
virtual void apply(C*)=0;
}
void A::apply(Functor_or_Operator* f)
{ f->apply(this);} //you need this only if A is not abstract (it is instantiable)
class B:public A
{
public:
void apply(Functor_or_Operator* f) { f->apply(this);} //dynamic dispatch , you call polymhorphic Functor f on this object
//..the rest of B implementation.
}
class C:public A
{
public:
void apply(Functor_or_Operator* f) { f->apply(this);} //dynamic dispatch , you call polymorfic Functor f on this object
//..the rest of C implementation.
}
class Functor_or_Operator_1:public Functor_or_Operator
{
public:
//implementations of application of a function represented by Functor_or_Operator_1 on each A,B,C
void apply(A*) {}//(only if A is instantiable,not an abstract class)
void apply(B*) {}
void apply(C*) {}
}
class Functor_or_Operator_2:public Functor_or_Operator
{
public:
//implementations of application of a function represented by Functor_or_Operator_2 on each A,B,C
void apply(A*) {}//(only if A is instantiable,not an abstract class)
void apply(B*) {}
void apply(C*) {}
}
para un ejemplo completo, ver el ejemplo en java http://en.wikipedia.org/wiki/Visitor_pattern#Java_example – stefaanv
En ese ejemplo se podría hacer fácilmente equipmentVisitor sólo utilizan la visita función, con tres funciones sobrecargadas cada uno toma una equipemtVisited clase derivada diferente como el parámetro. Solo yo haría de esa clase un Visitador de equipos. –