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

发布于 2024-12-19 13:13:15 字数 1506 浏览 2 评论 0原文

我今天正在用访问者模式做一些作业,我创建了一个看起来有点像这样的访问者(从 维基百科):

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

“public void access(CarElement element)”方法有点丑陋(很长,如果添加更多 CarElements 则需要维护),但我想保留该方法,所以我尝试这样做那就更好了。

我最终尝试了这个:

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

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

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

I was doing some homework today with the visitor-pattern, and i made a visitor that looked somewhat like this (edited sample code from 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");
    }
}

The "public void visit(CarElement element)" method is kind of ugly (long and needs to be maintained if more CarElements are added) but i want to keep the method, so i tried to do it better.

I ended up trying this out:

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

But that just returns "visit(CarElement element)", even though element.getClass() returns the correct class, so it ends up in a infinite loop.

Does anyone know how to do, what i'm trying to do? (If it is even possible, i'm not sure).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

奢望 2024-12-26 13:13:15

您错过了访问者模式的美妙之处:必须位于 CarElement 接口中的 accept(CarElementVisitor) 方法,该方法使用适当的类型自行回调访问者。重新阅读维基百科文章。

You missed what makes the beauty of the visitor pattern: the accept(CarElementVisitor) method that must be in the CarElement interface, and which calls the visitor back with itself, using the approriate type. Re-read the wikipedia article.

缪败 2024-12-26 13:13:15

上一个版本的问题是您尝试在运行时使用 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());
    }

}

请注意,每次添加要访问的新类型时,您仍然需要扩展访问者接口。
并参见

希望这会有所帮助)

Your problem with last version is that you try to use overloading during run-time which Java doesn't support. Java can dispatch call to various implementations based on type of object whose method is called, not on the type of argument.

Here's sample of Visitor pattern which will work as you (hopefully) want:

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

}

Note that you still need to extend Visitor interface every time you add new types to visit.
And see this answer of mine.

Hope, this helps a bit )

甚是思念 2024-12-26 13:13:15

您可以在 CarElement 上拥有一个抽象方法。

public abstract void visit();

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

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

You can have an abstract method on CarElement.

public abstract void visit();

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

CarElement ce = new Wheel();
ce.visit();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文