Tengo una jerarquía de clases que representa los controles de la GUI. Algo como esto:
Control->ContainerControl->Form
Tengo que implementar una serie de algoritmos que funcionan con objetos que hacen varias cosas y estoy pensando que el patrón de visitante sería la solución más limpia. Tomemos, por ejemplo, un algoritmo que crea una representación Xml de una jerarquía de objetos. Usando el enfoque 'clásico', haría esto:
public abstract class Control
{
public virtual XmlElement ToXML(XmlDocument document)
{
XmlElement xml = document.CreateElement(this.GetType().Name);
// Create element, fill it with attributes declared with control
return xml;
}
}
public abstract class ContainerControl : Control
{
public override XmlElement ToXML(XmlDocument document)
{
XmlElement xml = base.ToXML(document);
// Use forech to fill XmlElement with child XmlElements
return xml;
}
}
public class Form : ContainerControl
{
public override XmlElement ToXML(XmlDocument document)
{
XmlElement xml = base.ToXML(document);
// Fill remaining elements declared in Form class
return xml;
}
}
Pero no estoy seguro de cómo hacer esto con el patrón de visitante. Esta es la implementación básica:
public class ToXmlVisitor : IVisitor
{
public void Visit(Form form)
{
}
}
Dado que incluso las clases abstractas ayudan con la implementación, no estoy seguro de cómo hacerlo correctamente en ToXmlVisitor.
La razón por la que estoy considerando el patrón de visitante es que algunos algoritmos necesitarán referencias no disponibles en el proyecto donde se implementan las clases y hay una serie de algoritmos diferentes, por lo que estoy evitando clases grandes.
Respuestas:
El patrón de visitante es un mecanismo para simular doble enlace en lenguajes de programación que solo admiten enlace único. Desafortunadamente, esa declaración podría no aclarar mucho las cosas, así que permítanme explicarlo con un ejemplo simple.
En .NET y C #, la plataforma que está utilizando, los objetos se pueden convertir en cadenas mediante la
ToString()
función. Lo que hace esa función, es decir, el código que se ejecuta, depende del tipo de objeto al que lo esté aplicando (es un método virtual). El código que se ejecuta depende de una cosa, el tipo de objeto, por lo tanto, el mecanismo utilizado se llama enlace único.Pero, ¿qué pasa si quiero tener más de una forma de convertir un objeto en una cadena, para cada tipo diferente de objeto? ¿Qué pasaría si quisiera tener dos formas de convertir objetos en cadenas, de modo que el código que se ejecuta dependa de dos cosas: no solo el objeto a convertir, sino también la forma en que queremos que se convierta?
Eso podría resolverse bien si tuviéramos doble enlace. Pero la mayoría de los lenguajes OO, incluido C #, solo admiten el enlace único.
El patrón de visitante resuelve el problema al convertir el enlace doble en dos enlaces únicos sucesivos.
En nuestro ejemplo anterior, usaría un método virtual en el objeto para convertir, que llama a un segundo método virtual en el objeto que implementa el algoritmo de conversión.
Pero eso implica que el objeto sobre el que desea aplicar el algoritmo debe colaborar con esto: debe tener soporte para el patrón de visitante integrado.
Parece que está utilizando las clases de formularios Windows Forms de .NET, que no tienen soporte para el patrón de visitante. Más específicamente, tendrían que tener un
public virtual void Accept(IVisitor)
método, que obviamente no tienen.Entonces, ¿cuál es la alternativa? Bueno, .NET no solo admite el enlace único, sino que también es compatible con el enlace dinámico, que es aún más potente que el enlace doble.
Para obtener más información sobre cómo aplicar esa técnica, que le permitirá resolver su problema (si lo entiendo bien), eche un vistazo a Farewell Visitor .
ACTUALIZAR:
Para aplicar la técnica a su problema específico, primero defina su método de extensión:
Cree el despachador dinámico:
Luego complete los métodos específicos:
fuente