Вы по-прежнему называете методы в обратном направлении от способа, которым я считаю, что шаблон традиционно используется. Visitable (или Element) обычно имеет метод accept, а Visitor - метод visitX. Я собираюсь использовать традиционную схему именования, чтобы не запутаться: -)
IMO Самый простой способ заставить это работать - использовать несколько методов в интерфейсе посетителя, по одному для каждого типа детей. Не имеет значения, являются ли дети того же типа языка или нет, если они семантически отличаются, они должны обрабатываться разными методами.
Вам также следует избегать загрязнения реализации Visitor сведениями о структуре Visitable. Для этого я бы переместил метод accept в интерфейс Visitable вместо того, чтобы выставлять childA и childB на этом интерфейсе. Затем каждая реализация Visitable может решить, какой метод посетителю вызывать для каждого ребенка. Это сообщает посетителю весь контекст «местоположения» и дает вам хорошее, чистое, отделенное решение.
Вот пример того, о чем я думаю. Я снова поменял имена методов на те, к которым привык.
interface Visitable {
accept(Visitor v)
}
interface Visitor {
visitA(Node a)
visitB(Node b)
}
class Container implements Visitable {
private Node childA
private Node childB
...
void accept(Visitor v) {
v.visitA(childA)
v.visitB(childB)
}
}
Теперь у вас есть реализация Visitor, которая имеет 2 различных метода: один для обработки дочерних элементов A и один для обработки дочерних элементов B.