2009-02-09 3 views
2

Скажем, у меня есть посетитель, как этотКак должна быть передана информация о местоположении в шаблоне посетителя?

class Visitor : IVisitor 
{ 
    void Accept(Visitable v) 
    { 
     /// other code 
     v.AChild.Visit(this); 
     v.BChild.Visit(this); 
    } 
} 

Где AChild и BChild может быть точно такой же тип, но посещение код необходимо различать между ними (он должен работать по-разному на AChild чем BChild). Каков наилучший способ сделать это?

  • комплект состояние в визитера и проверить его на следующий вызов
  • передать другой посетитель каждому ребенку
  • другой?

Я сожалею, я сделал это назад в первый раз (в настоящее время Accept был Visit). Теперь он соответствует the pattern as show in Wikipedia.

Все методы посещения выглядеть следующим образом:

void Visit(IVisitor v) { v.Accept(this); } 

ответ

0

на основе вашей архитектуры, вы должны просто позвонить v.Visit(this), и пусть ваша реализация Visitable определить, как работать с AChild и BChild.

Кроме того, считайте, что AChild и BChild должны быть частными членами вашего экземпляра Visitable.

+0

см. Этот вопрос немного на мой взгляд: http://stackoverflow.com/questions/522803 – BCS

+0

IIRC, как все должно работать, v.Visit (это) будет кодом, который попал в мою функцию – BCS

+0

I gut Посетите/принимайте назад. см. править – BCS

0

Учитывая следующую дополнительную информацию от ответа в a background question первоначально плакатом:

The visitor object is required to know the structure of the things it visits. That's OK, though. You're supposed to write specialized visit operations for each type of thing the visitor knows how to visit. This allows the visitor to decide how much it really wants to visit, and in what order.

Я хотел бы ответить: Создать специальный класс IVisitor, возможно, под названием ABChildVisitor, которая будет иметь посещения() метод, который знает, как пересечь AChild и BChild.

2

Вы все еще называете методы назад, так как я считаю, что шаблон традиционно используется. У 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 детей.

+0

У меня была ошибка в моем примере, см. edit :( – BCS

+0

Точка Visitable должна иметь метод accept (или в вашем случае посещения), в котором он называет разные методы для посетителя, которые придают ему соответствующее «местоположение», контекст –

+0

Я совпадаю с Wikipedia. Мы говорим об одном и том же? – BCS

Смежные вопросы