Страницы

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

суббота, 20 апреля 2019 г.

Паттерн “Посетитель”. 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
Однако попадаю как видно только в метод для суперкласса. В общем, как я понял, какой тип указателя, такая функция вызывается. Я могу как то изменить это поведение? Чтобы вызывалась функция для фактического типа или я где-то тупанул с паттерном?


Ответ

Потому что всё совершенно не так.
Во-первых интерфейс визитёра должен объявлять методы для всех классов иерархии
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 конкретного класса, который в свою очередь вызывает "свой" перегруженный метод визитёра.

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

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