根据我找到的代码,似乎观众需要知道的访问对象的结构和所需要的孩子们叫。这似乎有点在某些情况下,笨重的地方游客会想继续工作,即使当访问类被修改。

我想真正的问题是:是它们在枚举通过访问代码完成,而不是访问者代码的模式

有帮助吗?

解决方案

访问者对象的知道它访问的事物的结构需要。这是确定的,虽然。你的应该的写访问专门为操作每种类型的东西访问者知道如何访问。这使得访问者多少来决定是否真的要来参观,以什么顺序。

假设你有一棵树。一位观众可能会做一个前序遍历,人们可能会做一个中序遍历,还有一个访客可能会在叶子节点只采取行动。访问者类可以做所有这些事情,而不需要对树类的任何更改。

访问者知道的结构中,但是,这并不一定意味着访问者执行操作知道所有的结构。你可能会用的命令结合访问者的。给访问者对象的命令对象,并且访问者将调用它访问每个事物的命令。

如果你想有一个简单的操作,让收集给你的每个项目采取行动,那么你要收集,为自身提供的迭代器即可。呼吁迭代器给你每一件事情的功能。

如果你想遍历各种顺序树的节点,则树将需要提供多个迭代器。如果你要处理节点的顺序是树的不已经支持,你需要修改树类。

其他提示

是。被访问的对象可以做枚举(即在需要的儿童的呼叫)。这仍是被称为“访问者”模式(实际上,设计模式的访客的第一样本确实是这样)。我的制造的例子片段:

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

注:探望子女,我们不能说visitor.visit(n);。这是因为Java不动态地选择方法(基于运行时类的它的参数),但静态选择方法(通过它的参数的编译时类型)。

在短的话,我认为要列举的方式完成访问者模式是正交的。这是可以做到无论哪种方式,或没有枚举的。

我认为,游客需要知道的访问结构包括哪些要素。想知道汽车是由车轮和发动机。要知道他们究竟是如何结合是没有必要的,我想。考虑下面的例子。知情人知道访问对象的结构和执行枚举本身。外人不知道它和代表枚举的访问对象。

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

我与访问者模式的广泛使用的一个项目,没有任何枚举的。我们有基本接口场和许多类实现它,像StringField,NumberField等很多时候,我们有基于字段类型做不同的事情,例如从DB,导出到XML等使其以不同的方式,负载我们可以定义在现场接口的方法,但是这将使它再加上项目的每一个功能 - 场差已经知道有关导出,导入,渲染到HTML和RTF等,我们也可以使用instanceof,但设置的可能实现现场接口类是随着时间改变,有可能添加新的字段类型和忘记添加

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

某处。所以我们决定使用访问者模式,它是像

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

如任何外地执行需要具有方法

void accept(FieldVisitor visitor)

然后如果我添加新的实施领域的接口,我必须以某种方式实现它。一般而言,这是

visitor.visit(this);

,其中该设备是新添加的类。这迫使我补充

void visit(NewlyAddedClass visited);

要FieldVisitor接口,这点让我实现它,我们已经有充分的FieldVisitor实施。所以,如果我忘了做这个事情 - 我会得到编译器错误。 在这种情况下枚举,如果有的话,被访问的结构和游客外完成。但我仍然认为它是访问者模式的一个有效的情况下。 它的发生是有点困难实现,但更容易和安全使用。

分层访问者模式解释了不同的方法,其中它增加了进入和离开事件水平。相关的讨论页面提出论据迭代是游客或在容器内。它包括使用外部迭代器这对我来说很有意义,如果你有一个普通的树和需要遍历不同的建议。

回顾我的 oofRep游客它有一个系列的水平的不同的类访问和方法内有迭代等:

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

与超控

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

看一看在此文章说明。

维基

  

在面向对象的编程和   软件工程,访问者   设计模式是分离的一种方式   从物体结构的算法   在其开展业务。实用   这种分离的结果是   新的操作添加到能力   现有的对象结构而不   修改这些结构。从而,   使用访问者模式有助于   与开启/关闭的一致性   原理

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top