一些非常通用的代码,带有访问者模式

时间:2011-12-05 19:30:06

标签: java visitor-pattern

今天我正在用访客模式做一些功课,我做了一个看起来有点像这样的访客(来自wikipedia的编辑样本代码):

class CarElementPrintVisitor implements CarElementVisitor {
    public void visit(CarElement element) {      
        if (element.getClass() == Wheel.class)
        {
            return visit((Wheel)element);
        }
        else if (element.getClass() == Engine.class)
        {
            return visit((Engine)element);
        }
        else if (element.getClass() == Body.class)
        {
            return visit((Body)element);
        }
        else //if (v.getClass() == Car car.class)
        {
            return visit((Car)element);
        }
    }

    public void visit(Wheel wheel) {      
        System.out.println("Visiting " + wheel.getName() + " wheel");
    }

    public void visit(Engine engine) {
        System.out.println("Visiting engine");
    }

    public void visit(Body body) {
        System.out.println("Visiting body");
    }

    public void visit(Car car) {      
        System.out.println("Visiting car");
    }
}

“公共无效访问(CarElement元素)”方法有点难看(如果添加更多CarElements需要维护很长时间)但是我想保留方法,所以我试着做得更好。

我最终尝试了这个:

    public void visit(CarElement element) {      
        return visit(element.getClass().cast(element));
    }

但是只返回“visit(CarElement element)”,即使element.getClass()返回正确的类,所以它最终会进入无限循环。

有谁知道怎么做,我想做什么? (如果有可能,我不确定)。

3 个答案:

答案 0 :(得分:3)

您错过了访问者模式的优点:必须在CarElement界面中使用accept(CarElementVisitor)方法,并使用approriate类型调用访问者自身。重新阅读维基百科文章。

答案 1 :(得分:1)

上一版本的问题是您尝试在Java不支持的运行时使用重载。 Java可以根据调用方法的对象类型调用各种实现,而不是调用参数类型。

以下是访客模式的示例,它可以像你(希望)那样工作:

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

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

interface Visitor {
    void visit(EventA e);
    void visit(EventB e);
}

class VisitorImpl implements Visitor {
    public void visit(EventA e) {
        System.out.println("EventA");
    }

    public void visit(EventB e) {
        System.out.println("EventB");
    }
}

public class Main {

    public static void main(String[] args) {
        EventA event = new EventA();
        event.accept(new VisitorImpl());
    }

}

请注意,每次添加要访问的新类型时,仍需要扩展Visitor界面。 请参阅我的this回答。

希望,这有点帮助)

答案 2 :(得分:0)

您可以在CarElement上使用抽象方法。

public abstract void visit();

class Wheel extends CarElement {
    public void visit() {
        System.out.println("Visiting " + getName() + " wheel");
    }
}

CarElement ce = new Wheel();
ce.visit();