Вопросы о шаблоне Visitor (пример на Java)

Я просто пытаюсь понять основные преимущества использования шаблона Visitor.

Вот пример реализации 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 (...) в части модели.

Во многих найденных мной примерах кажется, что они не используют общий интерфейс для объектов модели. Я добавил его, потому что мне просто нужно добавить метод одного посещения (Mammal) вместо того, чтобы реализовывать по одному для каждого Mammal. Хорошо ли, что все мои объекты реализуют Mammal? (я думаю, иногда это все равно невозможно). Это все еще паттерн "Посетитель"?

Итак, мои вопросы: - видите ли вы в моем примере преимущества использования посетителей? - если нет, можете ли вы предоставить посетителям конкретные варианты использования? - полезны ли посетители в языках функционального программирования

Единственный пример, который я нашел уместным для этого шаблона, - это случай симпатичного принтера, где вы сохраняете в состоянии посетителя смещение, используемое во время посещения различных узлов (для отображения XML-дерево для примера)

6
задан Dave Schweisguth 14 February 2016 в 00:06
поделиться