Ich denke, der Name des Musters Besucher ist ziemlich unglücklich. Anstelle des Wortes Besucher würde ich Functor oder Operator sagen und statt "besuchen" würde ich "anwenden" sagen.
Mein Verständnis von Besuchermuster ist wie folgt:
In Vorlage Meta-Programmierung (STL/BOOST) (Kompilierung Bindung) Sie können (das orthogonale Design) die Trennungen von Operationen von Strukturen erreichen, durch die mittels Funktionsobjekte (Funktoren.) zum Beispiel in
template <class RandomAccessIterator, class Compare>
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
ist die comp einen Funktor/Operator ‚kleiner als‘ Betrieb in einem sehr allgemeiner Weise darstellt, so dass Sie viele nicht-Varianten Art haben müssen Funktion:
Für Besuchermuster möchten Sie etwas Ähnliches erreichen, aber im Falle der Laufzeit (spät) Bindung:
Sie möchten die Schnittstelle von A vereinfachen, Sie wollen die Möglichkeit für zukünftige Erweiterungen (neue Operationen arbeiten mit A) und Sie wollen die Stabilität der Schnittstelle von A bei diesen Erweiterungen erreichen.
Von der ursprünglichen ‚Fett‘ Klasse:
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:
//....
}
Sie entfernen so viel Funktion von öffentlicher Schnittstelle wie möglich (solange sie im Hinblick auf den nicht-extrahierten Funktionen derselben öffentlichen Schnittstelle implementiert werden kann) und die Operationen wie die Funktors Objekte oder Objekte aus einer neuen functor Hierarchie darstellen:
Sie die Anzahl der Funktion in der Basisklasse reduzieren, indem er sehr generische Schnittstelle mit nach vorn erklärt Functor_or_Operator:
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:
//....
}
// Nun haben Sie N (= 3) Klassen in A-Hierarchie (A, B, C) und M-Operationen oder Funktionen repräsentiert durch Klassen in Functor_oder_Operator-Hierarchie Sie müssen N * M-Definitionen implementieren, wie jeder Operation von Functor_or_Operator funktioniert für jede Klasse in A-Hierarchie. Die große Sache ist, Sie können es tun, ohne die Schnittstelle der Klasse 'A' zu ändern. Die Deklaration der Klasse 'A' wird sehr stabil bei den neuen Hinzufügungen beim Einfügen neuer Operationen oder Funktionen, die mit Objekten der A-Hierarchie arbeiten oder bei neuen abgeleiteten Klassen in der A-Hierarchie. Die Stabilität von A (keine Änderungen an A) in Gegenwart von Hinzufügungen ist wichtig, um eine kostspielige (und manchmal unmögliche) Neukompilierung von Software zu vermeiden, die an vielen Stellen Header von A enthält.
Für jede neue Klasse in der A-Hierarchie erweitern Sie die Definition der Basis Functor_or_Operator, Sie fügen neue Implementierungsdateien hinzu, aber Sie müssen nie die Kopfzeile der Basisklasse A (normalerweise Schnittstelle oder abstrakte Klasse) berühren.
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*) {}
}
für ein vollständiges Beispiel finden Sie in das Java-Beispiel in http://en.wikipedia.org/wiki/Visitor_pattern#Java_example – stefaanv
In diesem Beispiel, das Sie einfach nur equipmentVisitor die Funktion Besuch nutzen machen könnten, mit drei überladenen Funktionen jeder nimmt eine andere abgeleitete equipemtVisited-Klasse als Parameter. Nur ich würde diese Klasse zum Ausrüstungsbesucher machen. –