Вы, вероятно, должны сравнивать шаблон посетителя с шаблоном метода шаблона, поскольку это две вещи, которые вы можете сравнивать и сравнивать.
Сравнение шаблона посетителя с методами расширения похоже на сравнение автомобиля с велосипедной звездочкой.
В любом случае методы расширения полезны везде, где полезен не виртуальный метод, с дополнительным бонусом, которыйвам не нужно владеть типом для определения метода расширения.
И шаблонный метод, и шаблон посетителя являются шаблонами проектирования, предназначенными для работы над деревьями объектов.«Классическое» определение обоих требует наличия виртуального метода в каждом «типе узла» в дереве объектов.Тем не менее, при необходимости можно реализовать оба с использованием не виртуальных методов.Существуют некоторые ограничения, такие как доступ к закрытым и защищенным элементам, но игнорируя это, любой шаблон может быть реализован с помощью методов расширения.
Шаблон метода шаблона работает путем добавления виртуального метода для операции к каждому типу вдерево объектов с "агрегатными узлами", вызывающими метод на их содержащихся узлах.
Примером может быть метод "print" для дерева выражений.
public class Node
{
abstract void print();
}
public class AddExpression : Node {
Node Left;
Node Right;
virtual void print() {
Left.Print();
Console.WriteLine("+");
Right.Print();
}
}
Это имеетглавное преимущество в том, что добавление новых типов узлов требует только дополнительных усилий.Только новые типы должны быть изменены.Однако у него есть недостаток, заключающийся в том, что добавление новых операций требует редактирования каждого отдельного типа.
Шаблон посетителя обобщает методы шаблона в единый метод с именем accept, который принимает объект посетителя в качестве параметра.Это выглядит примерно так:
interface Visitor {
void VisitAdd(AddExpression e);
void VisitSubtract(SubtractExpression e);
}
abstract class Node {
abstract void Accept(Visitor v);
}
class AddExpression : Node {
//...
virtual void Accept(Visitor v) {
Left.Accept(v);
v.VisitAdd(this);
Right.Accept(v);
}
}
Это имеет противоположные компромиссы.Добавление новых операций требует написания только одного нового класса, но добавление нового типа требует редактирования каждой операции.
Классический совет - использовать шаблонный метод, когда операции (относительно фиксированные), но новые типы объектов можно часто добавлять,Аналогично, посетители должны использоваться, когда типизированный объект зафиксирован, но новые операции могут добавляться часто,
Если оба варианта изменяются одинаково, то ваше решение должно основываться на балансировке:
- Ясность (методы шаблона проще для понимания и позволяют избежать затрат на двойную диспетчеризацию).
- Повторное использование (посетители учитывают общий код обхода в одном месте).