J'ai une hiérarchie de classes qui représente les contrôles GUI. Quelque chose comme ça:
Control->ContainerControl->Form
Je dois implémenter une série d'algorithmes qui fonctionnent avec des objets faisant diverses choses et je pense que le modèle de visiteur serait la solution la plus propre. Prenons par exemple un algorithme qui crée une représentation XML d'une hiérarchie d'objets. En utilisant une approche «classique», je ferais ceci:
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;
}
}
Mais je ne sais pas comment faire cela avec le modèle de visiteur. Voici l'implémentation de base:
public class ToXmlVisitor : IVisitor
{
public void Visit(Form form)
{
}
}
Étant donné que même les classes abstraites aident à l'implémentation, je ne sais pas comment le faire correctement dans ToXmlVisitor?
La raison pour laquelle je considère le modèle de visiteur est que certains algorithmes auront besoin de références non disponibles dans le projet où les classes sont implémentées et qu'il existe un certain nombre d'algorithmes différents, donc j'évite les grandes classes.
Réponses:
Le modèle de visiteur est un mécanisme permettant de simuler une double liaison dans des langages de programmation qui ne prennent en charge qu'une seule liaison. Malheureusement, cette déclaration peut ne pas clarifier beaucoup les choses, alors laissez-moi vous expliquer avec un exemple simple.
Dans .NET et C #, la plateforme que vous utilisez, les objets peuvent être convertis en chaînes à l'aide de la
ToString()
fonction. Ce que fait cette fonction, c'est-à-dire le code en cours d'exécution, dépend du type d'objet auquel vous l'appliquez (c'est une méthode virtuelle). Le code exécuté dépend d'une chose, du type d'objet, c'est pourquoi le mécanisme utilisé est appelé liaison simple.Mais que se passe-t-il si je veux avoir plus d'une façon de convertir un objet en chaîne, pour chaque type d'objet différent? Et si je voulais avoir deux façons de convertir des objets en chaînes, de sorte que le code en cours d'exécution dépend de deux choses: non seulement l'objet à convertir, mais aussi la manière dont nous voulons qu'il soit converti?
Cela pourrait être bien résolu si nous avions une double liaison. Mais la plupart des langages OO, y compris C #, ne prennent en charge que la liaison unique.
Le modèle de visiteur résout le problème en transformant la double liaison en deux liaisons simples successives.
Dans notre exemple ci-dessus, il utiliserait une méthode virtuelle dans l'objet à convertir, qui appelle une deuxième méthode virtuelle dans l'objet implémentant l'algorithme de conversion.
Mais cela implique que l'objet sur lequel vous souhaitez appliquer l'algorithme doit collaborer avec cela: il doit prendre en charge le modèle de visiteur intégré.
Vous semblez utiliser les classes Windows Forms de .NET, qui ne prennent pas en charge le modèle de visiteur. Plus précisément, ils auraient besoin d'une
public virtual void Accept(IVisitor)
méthode, ce qu'ils n'ont évidemment pas.Alors, quelle est l'alternative? Eh bien, .NET ne prend pas seulement en charge la liaison simple, il prend également en charge la liaison dynamique, ce qui est encore plus puissant que la double liaison.
Pour plus d'informations sur la façon d'appliquer cette technique, qui vous permettra de résoudre votre problème (si je le comprends bien), jetez un œil à Farewell Visitor .
MISE À JOUR:
Pour appliquer la technique à votre problème spécifique, définissez d'abord votre méthode d'extension:
Créez le répartiteur dynamique:
Remplissez ensuite les méthodes spécifiques:
la source