Я просто пытаюсь понять основные преимущества использования шаблона посетителя.
Вот пример реализации Java
///////////////////////////////////
// Interfaces
interface MamalVisitor {
void visit(Mammal mammal);
}
interface MammalVisitable {
public void accept(MamalVisitor visitor);
}
interface Mammal extends MammalVisitable {
public int getLegsNumber();
}
///////////////////////////////////
///////////////////////////////////
// Model
class Human implements Mammal {
@Override
public void accept(MamalVisitor visitor) { visitor.visit(this); }
@Override
public int getLegsNumber() { return 2; }
}
//PIRATE HAS A WOOD LEG
class Pirate extends Human {
@Override
public int getLegsNumber() { return 1; }
public int getWoodLegNumber() { return 1; }
}
class Dog implements Mammal {
@Override
public void accept(MamalVisitor visitor) { visitor.visit(this); }
@Override
public int getLegsNumber() { return 4; }
}
///////////////////////////////////
///////////////////////////////////
class LegCounterVisitor implements MamalVisitor {
private int legNumber = 0;
@Override
public void visit(Mammal mammal) { legNumber += mammal.getLegsNumber(); }
public int getLegNumber() { return legNumber; }
}
class WoodLegCounterVisitor implements MamalVisitor {
private int woodLegNumber = 0;
@Override
public void visit(Mammal mammal) {
// perhaps bad but i'm lazy
if ( mammal instanceof Pirate ) {
woodLegNumber += ((Pirate) mammal).getWoodLegNumber();
}
}
public int getWoodLegNumber() { return woodLegNumber; }
}
///////////////////////////////////
///////////////////////////////////
public class Main {
public static void main(String[] args) {
// Create a list with 9 mammal legs and 3 pirate woodlegs
List<Mammal> mammalList = Arrays.asList(
new Pirate(),
new Dog(),
new Human(),
new Pirate(),
new Pirate()
);
///////////////////////////////////
// The visitor method
LegCounterVisitor legCounterVisitor = new LegCounterVisitor();
WoodLegCounterVisitor woodLegCounterVisitor = new WoodLegCounterVisitor();
for ( Mammal mammal : mammalList ) {
mammal.accept(legCounterVisitor);
mammal.accept(woodLegCounterVisitor);
// why not also using:
// legCounterVisitor.visit(mammal);
// woodLegCounterVisitor.visit(mammal);
}
System.out.println("Number of legs:" + legCounterVisitor.getLegNumber());
System.out.println("Number of wood legs:" + woodLegCounterVisitor.getWoodLegNumber());
///////////////////////////////////
// The standart method
int legNumber = 0;
int woodLegNumber = 0;
for ( Mammal mammal : mammalList ) {
legNumber += mammal.getLegsNumber();
// perhaps bad but i'm lazy
if ( mammal instanceof Pirate ) {
woodLegNumber += ((Pirate) mammal).getWoodLegNumber();
}
}
System.out.println("Number of legs:" + legNumber);
System.out.println("Number of wood legs:" + woodLegNumber);
}
}
///////////////////////////////////
Мне просто интересно, каково главное преимущество для этого случая в использовании такого шаблона. Мы также можем перебрать коллекцию и получить почти то же самое, за исключением того, что нам не нужно обрабатывать новый интерфейс и добавлять шаблонный код в модель ...
С Apache Commons, или функциональным языком, классический способ, кажется, выполняет некоторую операцию отображения / уменьшения (отображение на номера ветвей и уменьшение с добавлением), и это довольно просто ...
Мне также интересно, почему мы используем
mammal.accept(legCounterVisitor);
mammal.accept(woodLegCounterVisitor);
а не
legCounterVisitor.visit(mammal);
woodLegCounterVisitor.visit(mammal);
Второй вариант, по-видимому, удаляет метод accept (...) для модельной детали.
Во многих образцах, которые я обнаружил, кажется, что они не используют общий интерфейс для объектов модели. Я добавил его, потому что мне просто нужно добавить один метод посещения (Млекопитающее) вместо того, чтобы реализовать один для каждого Млекопитающего.
Это хорошо, что все мои объекты реализуют Млекопитающее? (Думаю, иногда это просто невозможно). Это все еще шаблон посетителя?
Итак, мои вопросы:
- Видите ли вы в моем примере преимущество использования посетителей?
- если нет, можете ли вы предоставить конкретные примеры использования для посетителей?
- полезны ли посетители на функциональных языках программирования
Единственный пример, который я нашел релевантным для этого шаблона, это случай симпатичного принтера, где вы сохраняете в состоянии посетителя смещение, которое будет использоваться при посещении различных узлов (для отображения дерева XML для примера)