Pregunta

Basado en el código que he encontrado, parece que el Visitante se requiere para conocer la estructura de la visitó objetos y llamar a los niños.Esto parece un poco torpe en algunos casos donde el visitante querría seguir trabajando incluso si el visitado las clases son modificados.

Supongo que la pregunta real es: Es su un patrón en el que la enumeración realizada por el visitado código en lugar de los visitantes de código?

¿Fue útil?

Solución

El visitante objeto es se requiere conocer la estructura de las cosas que visitas.Eso está bien, sin embargo.Estás supone para escribir especializados visita de operaciones para cada tipo de cosa de la que el visitante sabe cómo visitar.Esto permite que el visitante decida cuánto quiere realmente a visitar y en qué orden.

Supongamos que usted tiene un árbol.Un visitante puede hacer un recorrido en orden previo, uno podría hacer un orden de recorrido, y, sin embargo, otro visitante puede actuar sólo en los nodos hoja.El visitante clases puede hacer todas estas cosas sin necesidad de cambios a la clase de árbol.

El visitante conoce la estructura, pero eso no necesariamente significa que la operación el visitante realiza conozca toda la estructura.Usted puede combinar un visitante con un comando.Dar al visitante objeto un objeto de comando, y el visitante podrá invocar el comando en cada cosa que visita.

Si usted quiere tener una operación sencilla y vamos a la colección de darle a cada elemento para actuar en, a continuación, desea que la colección de proporcionar una iterador para sí mismo.Llame a su función en cada cosa el iterador le da.

Si desea iterar a través de los nodos del árbol en diversos órdenes, entonces el árbol de la necesidad de ofrecer varios iteradores.Si desea proceso de nodos en un orden que el árbol no ya de apoyo, tendrá que modificar la clase de árbol.

Otros consejos

Sí. Los objetos visitados pueden hacer la enumeración (es decir, la llamada de los niños más necesitados). Esto todavía se llama el patrón de "Visitante" (de hecho, Diseño del patrón 's primera muestra de visitante lo hace de esta manera). Mi fragmento de ejemplo inventado:

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

Nota: para visitar a los niños, no podemos decir visitor.visit(n);. Esto se debe a Java no dinámicamente seleccionar el método (basado en la clase de tiempo de ejecución de sus argumentos), pero selecciona el método estáticamente (por el tipo de tiempo de compilación de sus argumentos).

En pocas palabras, creo que el patrón del visitante es ortogonal a la forma de hacer la enumeración. Se puede hacer de cualquier manera, o ninguna enumeración en absoluto.

Creo que es necesario que el visitante a saber qué elementos de la estructura visitado consiste en. Gustaría saber que el coche se compone de las ruedas y el motor. Para saber exactamente cómo se combinan no es necesario, creo. Considere siguiente ejemplo. Información privilegiada sabe estructura del objeto en sí visitado y realiza la enumeración. Extraño no lo sabe y los delegados de enumeración al objeto visitado.

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);
    }
}

Yo tenía un proyecto con amplio uso de patrón de visitante sin ningún tipo de enumeración en absoluto. Hemos tenido interfaz base Field y muchas clases de aplicación, como Stringfield, NumberField, etc. Muy a menudo hemos tenido que hacer cosas diferentes en función del tipo de campo, por ejemplo hacerla de una manera diferente, la carga de la base de datos, la exportación a XML, etc. . podríamos definir métodos de interfaz de campo, pero que lo haría junto con todas las características individuales del proyecto - pobres campo tiene que saber acerca de la exportación, la importación, lo que hace a hTML y RTF, etc. también podríamos utilizar instanceof pero conjunto de posibles las clases que implementan la interfaz de campo se cambian con el tiempo y que era posible añadir un nuevo tipo de campo y se olvide de añadir

else if (field instanceof NewlyAddedFieldType) {...}

en alguna parte. Así que decidimos utilizar el patrón de visitantes, y fue como

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

Como no se requiere ninguna aplicación Campo de tener método

void accept(FieldVisitor visitor)

Entonces, si añado la nueva aplicación de interfaz de campo, tengo que ponerlo en práctica alguna manera. Normalmente es

visitor.visit(this);

donde se trata de una clase recién añadido. Esto me obliga a añadir

void visit(NewlyAddedClass visited);

para FieldVisitor interfaz, lo que me hace implementarlo en todas las implementaciones FieldVisitor que ya tenemos. Así que si me olvido de hacer algo de esto - Voy a error del compilador. Enumeración en este caso, en su caso, se realiza fuera de la estructura visitado y visitante. Pero aún así pienso en ello como un caso válido de patrón de visitante. Resultamos ser un poco más difícil de implementar, pero más fácil y seguro de usar.

jerárquica de Visitantes explica un enfoque diferente en la que añade los eventos de entrada y salida los niveles. El página de discusión presenta argumentos para la iteración está dentro del visitante o el contenedor. Incluye una sugerencia de utilizar un repetidor externo que tiene sentido para mí si usted tiene un árbol regular y necesita iterar diferente.

Mirando hacia atrás a mi oofRep visitante que tenía una serie de niveles de diferentes clases para visitar y tenía la iteración dentro de los métodos como:

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();
}

con una anulación

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";
}

Tener un vistazo a la explicación en este .

Wiki :

  

En la programación orientada a objetos y   ingeniería de software, el visitante   patrón de diseño es una manera de separar   un algoritmo a partir de una estructura de objetos   en el que opera. Un práctico   resultado de esta separación es el   posibilidad de añadir nuevas operaciones   estructuras de objetos existente sin   la modificación de esas estructuras. Así,   utilizando el patrón de visitante ayuda   La conformidad con el abierto / cerrado   principio.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top