Страницы

Поиск по вопросам

среда, 12 февраля 2020 г.

Паттерн “Посетитель”. Java

#java #шаблоны_проектирования


В первый раз реализую, и что-то не заработало.

public interface FieldVisitor {
    Object visit(Field field);
}


А это методы из реализации:

private FieldVisitor factory = new FieldVisitor() {
    public Object visit(PresetField presetField) {
        ....
    }

    public Object visit(StringField stringField) {
        ....
    }

    @Override
    public Object visit(Field field) {
        System.out.println(field.getClass());
        ....
    }
};


Вызываю так:

public Node getFieldFor(Field field) {
    return (Node) factory.visit(field);
}


Видно что приходят объекты разных классов:

class com.dma.params.model.field.PresetField
class com.dma.params.model.field.PresetField
class com.dma.params.model.field.NumberField
class com.dma.params.model.field.NumberField
class com.dma.params.model.field.StringField
class com.dma.params.model.field.BooleanField


Однако попадаю как видно только в метод для суперкласса. В общем, как я понял, какой
тип указателя, такая функция вызывается. Я могу как то изменить это поведение? Чтобы
вызывалась функция для фактического типа или я где-то тупанул с паттерном?
    


Ответы

Ответ 1



Потому что всё совершенно не так. Во-первых интерфейс визитёра должен объявлять методы для всех классов иерархии public interface FieldVisitor { Object visit(PresetField field); Object visit(StringField field); ... } Во-вторых родоначальник иерархии объявляет абстрактный метод accept, в котором принимается визитёр class Field { ... public abstract void accept(FieldVisitor visitor); ... } В-третьих конкретные такие потомки реализуют/переопределяют метод-акцептор таким образом, чтобы вызывался метод визитёра для нужного (своего) класса class StringField { ... @Override public abstract void accept(FieldVisitor visitor) { visitor.visit(this); // вызов visit(StringField field) } ... } Наконец визитёр может посетить иерархию, предварительно реализовав интерфейс визитёра вызовом акцептора ... field.accept(new FieldVisitor() { @Override Object visit(PresetField field) { ... } @Override Object visit(StringField field) { ... } }); ... Благодаря полиморфизму вызывается accept конкретного класса, который в свою очередь вызывает "свой" перегруженный метод визитёра.

Комментариев нет:

Отправить комментарий