En programación informática , el patrón de visitante de servicio único es un patrón de diseño . Su objetivo es optimizar la implementación de un visitante que se asigna, se utiliza solo una vez y luego se elimina (que es el caso de la mayoría de los visitantes).
Aplicabilidad
El patrón de visitante de un solo uso se debe utilizar cuando los visitantes no necesitan permanecer en la memoria. Este suele ser el caso cuando se visita una jerarquía de objetos (como cuando el patrón de visitante se utiliza junto con el patrón compuesto ) para realizar una única tarea en ellos, por ejemplo, contar la cantidad de cámaras en una escena 3D.
El patrón de visitante regular se debe utilizar cuando el visitante debe permanecer en la memoria. Esto ocurre cuando el visitante está configurado con una serie de parámetros que deben mantenerse en la memoria para un uso posterior del visitante (por ejemplo, para almacenar las opciones de renderizado de un renderizador de escenas 3D).
Sin embargo, si solo debe haber una instancia de dicho visitante en todo un programa, puede ser una buena idea implementarlo como visitante de servicio único y como singleton . De esta manera, se garantiza que el visitante de servicio único pueda ser llamado más tarde sin modificar sus parámetros (en este caso particular, "visitante de servicio único" es un abuso del lenguaje ya que el visitante puede usarse varias veces).
Ejemplos de uso
El visitante de servicio único se llama a través de la intermediación de métodos estáticos.
- Sin parámetros:
Elemento * elem ; SingleServingVisitor :: apply_to ( elem );
- Con parámetros:
Elemento * elem ; TIPO parámetro1 , parámetro2 ; SingleServingVisitor :: apply_to ( elem , parámetro1 , parámetro2 );
- Implementación como singleton:
Elemento * elem ; TIPO param1 , param2 ; SingleServingVisitor :: set_param1 ( param1 ); SingleServingVisitor :: set_param2 ( param2 ); SingleServingVisitor :: apply_to ( elem );
Consecuencias
Ventajas
- No hay objetos "zombis" . Con un visitante de un solo uso, se garantiza que los visitantes se distribuyan cuando se los necesita y se destruyan cuando ya no sirven.
- Una interfaz más sencilla que visitor . El visitor se crea, se utiliza y se libera con solo llamar al método estático apply_to .
Contras
- Asignación repetida . En cada llamada al método apply_to , se crea un visitante de servicio único y luego se descarta, lo que requiere mucho tiempo. Por el contrario, el singleton solo realiza una asignación.
Implementación (en C++)
Implementación básica (sin parámetros)
// Declaración
clase Elemento ; clase ElementoA ; clase ElementoB ; clase SingleServingVisitor ;
... // Lo mismo que con el [[patrón de visitante]].
// Definición
clase SingleServingVisitor { protected : SingleServingVisitor (); public : ~ SingleServingVisitor ();
void estático aplicar_a ( Elemento * ); void virtual visitar_ElementoA ( ElementoA * ) = 0 ; void virtual visitar_ElementoB ( ElementoB * ) = 0 ; }
// Implementación void SingleServingVisitor :: apply_to ( Element * elem ) { SingleServingVisitor ssv ; elem.accept ( ssv ) ; }
Pasando parámetros
Si es necesario inicializar el visitante de servicio único, los parámetros deben pasarse a través del método estático:
void SingleServingVisitor::apply_to ( Elemento * elem , TIPO parámetro1 , TIPO parámetro2 , ...) { SingleServingVisitor ssv ( parámetro1 , parámetro2 , ...); elem . accept ( & ssv ); }
Implementación como singleton
Esta implementación garantiza:
- que hay como máximo una instancia del visitante de servicio único
- que el visitante pueda acceder posteriormente
// Definición
clase SingleServingVisitor { protected : static SingleServingVisitor * instance_ ; TIPO param1_ ; TIPO param2_ ;
Visitante de servicio único ();
static SingleServingVisitor * get_instance (); // Nota: el método get_instance no necesita ser público
público :
~ SingleServingVisitor ();
void estático apply_to ( Elemento * );
// métodos estáticos para acceder a parámetros
static void set_param1 ( TYPE ); static void set_param2 ( TYPE );
vacío virtual visita_ElementoA ( ElementoA * ) = 0 ; vacío virtual visita_ElementoB ( ElementoB * ) = 0 ; }
// Implementación
SingleServingVisitor * SingleServingVisitor :: instancia_ = NULL ;
SingleServingVisitor * SingleServingVisitor::get_instance () { si ( esto -> instancia_ == NULL ) esto -> instancia_ = new SingleServingVisitor (); devolver esto -> instancia_ ; }
void SingleServingVisitor::apply_to ( Elemento * elem ) { elem -> accept ( obtener_instancia ()); }
void SingleServingVisitor::set_param1 ( TYPE param1 ) { getInstance () -> param1_ = param1 ; }
void SingleServingVisitor::set_param2 ( TYPE param2 ) { getInstance () -> param2_ = param2 ; }
Patrones relacionados
- Patrón de visitante , del cual se deriva este patrón
- Patrón compuesto : el visitante de servicio único se aplica a menudo a jerarquías de elementos
- Patrón singleton