Это не шаблон посетителя .
Для посетителя характерно наличие у посетителя метода accept(Visitor v)
, который взаимодействует с методом посещения у посетителя, принимая в качестве параметра посетителя и перегруженного для изменяемого типа посетителя, образуя механизм "двойной отправки".
Цитирование из раздела «Применимость» для посетителя в Шаблонах проектирования :
Используйте шаблон Visitor, когда
-
структура объекта содержит много
классы объектов с различными
интерфейсы, и вы хотите выполнить
операции на этих объектах, которые
зависит от их конкретных классов.
-
необходимо выполнить много разных и не связанных операций
объекты в структуре объекта и
Вы хотите избежать "загрязнения" их
классы с этими операциями.
Посетитель позволяет вам оставаться на связи
операции вместе, определяя их
в одном классе. Когда объект
структура разделяется многими
приложения, используйте Visitor, чтобы поставить
операции только в этих приложениях
которые нуждаются в них.
-
классы, определяющие структуру объекта, редко меняются, но вы
часто хотят определить новые операции
над структурой. Изменение
классы структуры объекта требует
переопределение интерфейса для всех
посетители, которые потенциально
дорогостоящий. Если структура объекта
классы часто меняются, то это
вероятно, лучше определить
операции в этих классах.
Таким образом, этот шаблон предназначен для работы с подобными операциями над объектами нескольких типов. В ваших примерах объекты, которые вы называете посетителями, могут иметь дело только с одним типом.
В своем ответе на изменение отражения для обработки нескольких типов (что, кстати, было бы лучше сделать как редактирование вопроса или как отдельный вопрос), вы избегаете создания метода accept(Visitor v)
в посещаемых классах. используя рефлексию, которая до некоторой степени выполняет ту же цель, но несколько неловко. Я все еще не стал бы называть это реализацией Visitor.
Если код в стиле, который вы написали здесь, вам полезен, во что бы то ни стало, используйте его, но, пожалуйста, не называйте его посетителем.
Это больше похоже на шаблон стратегии или функциональный объект , и если вы переименуете универсальный класс таким образом, который отражает это, это на самом деле полезно, и ваше использование похож на общие шаблоны обработки списков в функциональных языках.
Что я мог бы сделать с кодом из вопроса, так это переименовать ваш Visitor<T>
в Operation<T>
и переименовать ваш visit(T t)
в execute(T t)
или apply(T t)
, думая о Operation
как Function
без возвращаемого значения. На самом деле я использовал именно это так, как вы делаете, и использовал аналогичную тактику для «отображения» коллекций с использованием общих Function<Domain, Range>
объектов. Я не уверен, какое имя шаблона на самом деле ему подходит, но это не Visitor. Он привносит функциональный стиль понимания списка в мир ОО, где функции не являются объектами первого класса.