2008-12-12 16 views
27

Duplicado de: When Should I Use The Visitor Design Pattern¿Por qué utilizar el patrón de visitante?

¿Por qué alguien que desee utilizar el patrón de visitante? He leído un par de artículos, pero no obtengo nada.

Si necesito una función de facturar una costumbre, que podría utilizar

Custom.Accept(BillVisitor) 

o algo así

Bill(Customer) 

La segunda es menos complejo, y la función de Bill todavía se separa del Cliente clase. Entonces, ¿por qué querría usar el patrón de visitante?

+1

Véase también http://stackoverflow.com/questions/255214/when-should-i-use-the-visitor-design-pattern –

Respuesta

49

El problema surge cuando tiene una estructura compleja, es decir, una jerarquía u otra cosa que no es simplemente lineal. Cuando no se puede simplemente iterar sobre la estructura, un visitante es muy útil.

Si tengo una jerarquía (o árbol), cada nodo tiene una lista de elementos secundarios. Cuando quiero aplicar un proceso a cada nodo en el árbol, es agradable crear un Visitante.

Un nodo puede aplicar el visitante a sí mismo y a cada uno de sus Nodos secundarios. Cada niño, de manera transitiva, hace lo mismo (aplica el Visitante a sí mismo y luego a cualquier niño).

Este uso de un visitante funciona muy bien.

Cuando tiene una estructura de datos súper simple, Visitor no agrega mucho valor.

+1

Un ejemplo de una estructura tan compleja es el árbol de sintaxis en un compilador. – Shuo

+0

Por supuesto, el visitante no puede, por ejemplo, toString() un árbol, porque la visita (principal) no obtiene ninguno de los resultados de visita (secundarios) con los que trabajar. Entonces, para uno de los casos de uso más simples, el patrón de visitante es completamente * inútil *. – user1244215

+2

Vale la pena mencionar que esta respuesta describe el [Patrón de visitante jerárquico] (http://en.wikipedia.org/wiki/Hierarchical_visitor_pattern), opuesto al actual (poco nombrado) [Patrón de visitante] (http: //en.wikipedia .org/wiki/Visitor_pattern) que básicamente le permite agregar nuevas operaciones en clases existentes sin modificarlas, como se menciona en la respuesta de @ididak [abajo] (http://stackoverflow.com/a/362186/69809). El recorrido del árbol no es relevante para este patrón, aunque el nombre lo implica (tipo de). – Groo

1

En ambos casos, el visitante está separado de la clase de cliente. La ventaja sería si también quisieras abstraer al visitante de la clase de la persona que llama. En el segundo caso, la clase llamante debe saber acerca de la facturación. En su lugar, podría tener otra rutina en algún lugar que devuelva un IVisitor. El código de llamada podría llamar a Custom.Accept (IVisitor) y no saber nada sobre lo que está haciendo el visitante.

Básicamente en este caso y en el caso mencionado por S.Lott, puede pensar en el visitante como un delegado. Es una función que puede pasar como un objeto y usar donde sea necesario.

2

Otra buena ventaja de los visitantes, es que son fáciles de extender, y si su idioma lo permite, incluso puede usar lamdbas para limpiar cosas.

16

El patrón de visitante es un truco para los idiomas que no admiten el despacho múltiple directamente (el lenguaje como C++ y Java solo admiten el despacho único basado en el objeto. CLOS admite envíos múltiples). En este caso, si desea que tanto Bill como Customer sean polimórficos, deberá usar dos interfaces, BillVisitor y Customer en idiomas de despacho únicos. Por ejemplo: la puesta en práctica de aceptar es normalmente:

void accept(BillVisitor visitor) { visitor.bill(this); } // java syntax 

Aviso aquí, tanto para el cliente # aceptar y BillVisitor # proyecto de ley puede ser anulado por sus respectivas subclases, lo que resulta muy rica combinación de comportamiento en tiempo de ejecución que no se puede lograr de otro modo . En realidad, es un superconjunto de lo que la mayoría de la gente describe aquí como un sustituto del cierre para aplicar la funcionalidad a estructuras de datos complejas.

3

En mi aplicación CAD/CAM tengo Paths and Collections of Paths (PathList). A veces tengo que generar una colección de formas.No solo tengo que generar esta colección particular de formas, debo incluirla con otra colección de formas. A menudo necesito una docena o más de parámetros para transmitir toda la información necesaria para hacer los cálculos.

Todos los cálculos de forma (simples o complejos) en mi CAM se canalizan a PathList que se envía a las diferentes máquinas.

Con este diseño, sería mejor tener alguna configuración que implique agregar el resultado a una sola colección.

The Path Visitor se adapta muy bien. Cada cálculo de forma se encapsula en su propia clase con las propiedades tan complejas como sea necesario.

Así que el visitante puede Campana Cocina tenido 8 formas para la pathlist

Mientras que la preparación en la cocina de Visitantes añade 6 formas.

The drawer Visitor agrega algunos más.

Luego paso el PathList resultante al resto del sistema como cualquier otro generador de formas.

Fácilmente tengo opciones agregando otro visitante o no ejecutando algunos. Para un chico que solo quiere un mostrador y cajones, solo necesito correr dos visitas.

El código resultante es muy legible, lo cual es importante cuando vuelvo a visitar esta área 3, 5 o 10 años más adelante. Además, debido a los cambios de encapsulamiento en un visitante, tiene un impacto mínimo o nulo en otros visitantes.

Además, ahora tengo un patrón de diseño estandarizado para agregar cualquier funcionalidad nueva a PathList implementando el patrón de visitante.

Por ejemplo, solía ser que nuestro editor de propiedades solo funcionaba en una sola ruta. Cuando cambiamos a la edición de varias rutas, fue fácil implementar visitas personalizadas para realizar cambios globales en todas las rutas. Era más legible que usar bucles dentro de los delegados.

Pero en última instancia todo se reduce a juicio y preferencia.

Cuestiones relacionadas