Какой-то очень общий код с шаблоном посетителя - PullRequest
2 голосов
/ 05 декабря 2011

Сегодня я делал домашнюю работу с шаблоном посетителя, и сделал посетителя, который выглядел примерно так (отредактированный пример кода из 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");
    }
}

"public void visit (CarElement element) "метод довольно уродлив (длинен и требует сохранения, если добавлено больше CarElements), но я хочу сохранить метод, поэтому я попытался сделать это лучше.

В итоге я попробовал это:

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

Но это просто возвращает «посещение (элемент CarElement)», даже если element.getClass () возвращает правильный класс, поэтому он заканчиваетсяв бесконечном цикле.

Кто-нибудь знает, как это сделать, что я пытаюсь сделать?(Если это даже возможно, я не уверен).

Ответы [ 3 ]

3 голосов
/ 05 декабря 2011

Вы пропустили красоту шаблона посетителя: метод accept(CarElementVisitor), который должен быть в интерфейсе CarElement и который вызывает посетителя обратно с собой, используя тип approriate.Перечитайте статью в Википедии.

1 голос
/ 05 декабря 2011

Ваша проблема с последней версией заключается в том, что вы пытаетесь использовать перегрузку во время выполнения, которую Java не поддерживает.Java может отправлять вызов различным реализациям на основе типа объекта, метод которого вызывается, а не типа аргумента.

Вот пример шаблона Visitor, который будет работать так, как вы (надеемся) хотите:

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

}

Обратите внимание, что вам все равно нужно расширять интерфейс посетителя при каждом добавлении новых типов для посещения.И посмотрите этот мой ответ.

Надеюсь, это немного поможет)

0 голосов
/ 05 декабря 2011

Вы можете использовать абстрактный метод для CarElement.

public abstract void visit();

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

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