Frage

Auf der Basis der Code, den ich gefunden habe, scheint es, dass die Besucher erforderlich ist, die Struktur der besuchten Objekte bekannt und rufen die benötigten Kinder. Dies scheint ein bisschen klobig in einigen Fällen, in denen der Besucher weiterhin funktioniert auch, wenn die besuchten Klassen geändert wollen würde.

Ich denke, die wirkliche Frage ist: Ist sie ein Muster, bei dem die Aufzählung von dem besuchten Code erfolgt statt dem Besuchercode

War es hilfreich?

Lösung

Der Besucher Objekt ist erforderlich, um die Struktur der Dinge zu wissen, dass es besucht. Das ist in Ordnung, aber. Du bist sollte für jede Art von Sache spezialisierte Besuch Operationen schreiben der Besucher weiß, wie zu besuchen. Dies ermöglicht es dem Besucher, zu entscheiden, wie viel sie wirklich besuchen will, und in welcher Reihenfolge.

Angenommen, Sie haben einen Baum. Ein Besucher kann eine Pre-Order Traversal tun, könnte man ein In-Order-Traversal tun, und noch ein anderer Besucher könnte nur auf Blattknoten fungieren. Die Besucher Klassen können all diese Dinge tun, ohne Änderungen an der Baumklasse erforderlich ist.

Der Besucher kennt die Struktur, aber das bedeutet nicht unbedingt, der Betrieb der Besucher die ganze Struktur führt kennt. Sie können einen Besucher mit einem Befehl kombiniert . Geben Sie den Besucher ein Befehlsobjekt Objekt, und der Besucher rufen Sie den Befehl auf jede Sache, die es besucht.

Wenn Sie eine einfache Bedienung haben wollen und lassen Sie die Sammlung, die Sie jedes Element geben zu handeln, dann wollen Sie die Sammlung ein Iterator schaffen für sich. Rufen Sie Ihre Funktion an jeder Sache der Iterator gibt Ihnen.

Wenn Sie den Baum der Knoten in verschiedenen Reihenfolgen iterieren, dann wird der Baum müssen mehrere Iteratoren bieten. Wenn Sie Knoten verarbeiten, in einer Reihenfolge mögen, dass der Baum nicht bereits unterstützt, müssen Sie die Baum-Klasse ändern.

Andere Tipps

Ja. Die besuchten Objekte können die Aufzählung tun (das heißt Anruf auf die benötigten Kinder). Dies ist nach wie vor die „Besucher“ Muster (in der Tat, Design Muster 's erste Probe von Besuchern tut es auf diese Weise) genannt. Mein erfundenes Beispiel Snippet:

public void accept(Visitor visitor) {
  for (Node n : children) {
    n.accept(visitor);
  }
}

Hinweis: die Kinder für einen Besuch, können wir nicht sagen visitor.visit(n);. Dies liegt daran, dass Java nicht dynamisch die Methode auswählen (auf der Basis der Laufzeitklasse ihrer Argumente), sondern wählt die Methode statisch (durch den Kompilierung-Typen ihrer Argumente).

Kurz gesagt, ich denke, dass Besucher-Muster orthogonal zu der Art und Weise Aufzählung erfolgt. Es kann so oder so, oder keine Aufzählung überhaupt durchgeführt werden.

ich denke, dass Besucher erforderlich ist, zu wissen, welche Elemente besucht Struktur besteht aus. Gerne wissen, dass Auto Räder und Motor besteht. Um zu wissen, wie genau sie kombiniert werden, nicht notwendig ist, glaube ich. Betrachten wir folgendes Beispiel. Insider weiß Objektstruktur besucht und führt selbst Enumeration. Außenseiter nicht weiß es und Delegierten Aufzählung das besuchten Objekt.

interface Visitable {
    void accept(Visitor visitor);
}

class WorkingRoom implements Visitable {
    public int number;
    WorkingRoom(int number) {
        this.number = number;
    }

    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

class BossRoom implements Visitable {
    public String bossName;
    BossRoom(String bossName) {
        this.bossName = bossName;
    }
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

interface Visitor{
    void visit(WorkingRoom workingRoom);
    void visit(BossRoom bossRoom);
    void visit(Office office);
}

class Office implements Visitable{
    public Visitable[] firstFloor;
    public Visitable[] secondFloor;
    public Visitable ceoRoom;
    public Office(){
        firstFloor = new Visitable[]{ new WorkingRoom(101),
                                        new WorkingRoom(102),
                                        new BossRoom("Jeff Atwood"),
                                        new WorkingRoom(103)};
        secondFloor = new Visitable[]{  new WorkingRoom(201),
                                        new WorkingRoom(202),
                                        new BossRoom("Joel Spolsky")};

        ceoRoom = new BossRoom("Bill Gates");
    }

    public void accept(Visitor visitor) {
        visitor.visit(this);
    }

    public void showMeTheOffice(Visitor visitor, boolean sayPlease) {
        // Office manager decides the order in which rooms are visited
        for(int i=secondFloor.length-1; i >= 0; i--){
            secondFloor[i].accept(visitor);
        }
        if (sayPlease){
            ceoRoom.accept(visitor);
        }
        for (int i = 0; i < firstFloor.length; i++) {
            firstFloor[i].accept(visitor);
        }
    }
}

class Insider implements Visitor{
    public void visit(WorkingRoom workingRoom) {
        System.out.println("I> This is working room #"+workingRoom.number);
    }

    public void visit(BossRoom bossRoom) {
        System.out.println("I> Hi, "+bossRoom.bossName);
    }

    public void visit(Office office) {
        // I know about office structure, so I'll just go to the 1st floor
        for(int i=0;i<office.firstFloor.length;i++){
            office.firstFloor[i].accept(this);
        }
    }
}

class Outsider implements Visitor{

    public void visit(Office office) {
        // I do not know about office structure, but I know they have a 
        // nice office manager
        // I'll just ask to show me the office
        office.showMeTheOffice(this, true);
    }

    public void visit(WorkingRoom workingRoom) {
        System.out.println("O> Wow, room #"+workingRoom.number);
    }

    public void visit(BossRoom bossRoom) {
        System.out.println("O> Oh, look, this is "+bossRoom.bossName);
    }
}

public class Main{
    public static void main(String[] args) {
        Office office = new Office(); // visited structure
        // visitor who knows about office structure
        Insider employee = new Insider(); 
        office.accept(employee);
        System.out.println();
        // visitor who does not know about exact office structure
        // but knows something else
        Outsider candidate = new Outsider(); 
        office.accept(candidate);

        // no enumeration at all, but still a visitor pattern
        Visitable v = new BossRoom("Linus Torvalds");
        v.accept(candidate);
    }
}

hatte ich ein Projekt mit breiter Nutzung von Besuchermustern ohne überhaupt eine Aufzählung. Wir hatten Basis-Schnittstelle Feld und viele Klassen es Implementierung, wie Stringfield, Number, etc. Sehr oft haben wir verschiedene Dinge zu tun hatte, basierend auf dem Feldtyp, zum Beispiel machen es auf eine andere Art und Weise, Last von der DB, den Export in XML, etc. . Wir Methoden in Feld Schnittstelle definieren konnten, aber das wäre es mit jedem einzelnen Merkmale des Projektes gekoppelt machen - schlechtes Feld hat über Export, Import, Rendering HTML und rtf wissen, etc. Wir könnten auch instanceof aber möglich eingestellt verwenden Klassen-Feld-Schnittstelle implementiert wurde im Laufe der Zeit geändert, und es war möglich, neuen Feldtyp hinzuzufügen und vergisst

hinzufügen
else if (field instanceof NewlyAddedFieldType) {...}

irgendwo. Also haben wir beschlossen Besuchermuster zu verwenden, und es war wie

Visitor v = new XMLExportVisitor(outputStream);
field.accept(v);

Wie jede Feld Implementierung erforderlich Verfahren haben,

void accept(FieldVisitor visitor)

dann, wenn ich neue Implementierung von Feld Schnittstelle hinzufügen, ich habe es irgendwie zu implementieren. Normalerweise ist es

visitor.visit(this);

, wo dies eine neu hinzugefügte Klasse. Dies zwingt mich hinzufügen

void visit(NewlyAddedClass visited);

zu FieldVisitor-Schnittstelle, die mich in jeder FieldVisitor Umsetzung implementieren macht, die wir bereits haben. Also, wenn ich etwas vergessen dies zu tun - ich werde Compiler-Fehler. Enumeration in diesem Fall, wenn überhaupt, wurde außerhalb der besuchten Struktur und Besucher gemacht. Aber ich denke immer noch darüber als gültigen Fall von Besuchermustern. Es passiert etwas schwieriger zu implementieren, aber einfacher und sicherer zu nutzen.

Die Hierarchical Visitor Pattern einen anderen Ansatz erklärt, wo es Veranstaltungen für Betreten und Verlassen fügt Ebene. Die zugehörige Diskussion präsentiert Argumente für Iteration innerhalb des Besuchers oder dem Behälter zu sein. Es enthält einen Vorschlag, einen externen Iterator, die für mich Sinn macht, wenn Sie einen regelmäßigen Baum und müssen anders iterieren.

Im Rückblick auf meine oofRep Besucher es eine Reihe von Ebenen hatte verschiedene Klassen zu besuchen und hatten die Iteration innerhalb von Methoden wie:

void
oofRepVisitor::VisitViewHeaders(oofRepBandList& inBands)
{
    VisitBandList(inBands);
}


void
oofRepVisitor::VisitBandList(oofRepBandList& inBands)
{
    EnterLevel();
    const unsigned long numBands = inBands.count();
    for (unsigned long i=0; i<numBands; i++) {
        oofRepBand* theBand = inBands.value(i);
        assert(theBand);
        VisitTypedBand(theBand);
    }
    LeaveLevel();
}

mit einer Überschreibung

void
OOF_repXMLlayoutVisitor::VisitViewHeaders(oofRepBandList& inBands)
{
    oofRepStreamEnv::out() << mIdentities.getIndentString();
    if (inBands.keepTogether())
        oofRepStreamEnv::out()  << "<header>\n";    
    else  // default is ON, and simplifies XML
        oofRepStreamEnv::out()  << "<header keepTogether='false'>\n";
    VisitBandList(inBands);
    oofRepStreamEnv::out() 
        << mIdentities.getIndentString()
        << "</header>\n";
}

Haben Sie einen Blick auf die Erklärung in diesem Artikel .

Wiki :

  

In der objektorientierten Programmierung und   Software-Engineering, der Besucher   Designmuster ist ein Weg zur Trennung von   ein Algorithmus aus einer Objektstruktur   auf dem sie tätig ist. Ein praktisches   Durch diese Trennung ist die   Fähigkeit, neue Operationen in der   vorhandenen Objektstrukturen ohne   diese Strukturen modifiziert wird. Somit,   mit dem Besuchermuster hilft   Übereinstimmung mit der offen / geschlossen   Prinzip.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top