Разница между посетителем pattern & Double Dispatch



Я читаю о шаблоне посетителя, и он выглядит так же, как двойная отправка. Есть ли какая-то разница между ними?
Делать два термина означает одно и то же.



Ссылка: http://www.vincehuston.org/dp/visitor.html

753   5  

5 ответов:

Короче говоря

Они исходят из различных концептуализаций, которые в некоторых языках, где двойная отправка изначально не поддерживается, приводят к паттерну посетителя как способу объединения двух (или более) одиночных отправлений для того, чтобы иметь многоадресный суррогат.

В длинном

Идея множественной диспетчеризации-по существу-разрешает вызов, подобный

void fn(virtual base_a*, virtual base_b*); (примечание: не как член класса: это не C++! )

Это можно переопределить как

void fn(virtual derived_a1*, virtual derived_b1*);
void fn(virtual derived_a2*, virtual derived_b1*);
void fn(virtual derived_a1*, virtual derived_b2*);
void fn(virtual derived_a2*, virtual derived_b2*);

Так что, при вызове

fn(pa, pb)

Вызов перенаправляется на переопределение, которое соответствует фактическомутипу времени выполнения как pa, так и pb. (Вы можете обобщить это на любое число параметров)

В таких языках, как C++, C#, Java, этот механизм не существует, и диспетчеризация типов среды выполнения в основном работает только с одним параметром (который, будучи только одним, неявно включается в функцию, делая саму функцию членом класс:

Другими словами, псевдокод
void fn(virtual base_a*, base_b*) 

Становится (реальным C++)

class base_a
{
public:
    virtual void fn(base_b*);
}
Обратите внимание, что здесь нет больше virtual перед base_b, что отныне является статичным. Звонок вроде

pa->fn(pb) если pa указывает на derived_a2, а pb на derived_b1 будет отправлено в derived_a2:: fn (base_b*), независимо от того, есть ли там derived_a2::fn(derived_b1*): тип времени выполнения объекта, на который указывает pb, не учитывается.

Идея посетителя Паттер заключается в том, что вы вызываете виртуальную отправку объекта, который вызывает (в конечном итоге) виртуальную отправку другого:

class base_a
{
public:
   virtual void fn(base_b*)=0;
   virtual void on_visit(derived_b1*)=0;
   virtual void on_visit(derived_b2*)=0;
};

class base_b
{
public:
   virtual void on_call(derived_a1*)=0;
   virtual void on_call(derived_a2*)=0;
};

//forward declarations, to allow pointers free use in other decls.
class derived_a1;
class derived_b1;


class derived_a1: public base_a
{
public:
   virtual void fn(base_b* pb) { pb->on_call(this); }
   virtual void on_visit(derived_b1* p1) { /* useful stuff */ }
   ...
};

class derived_b1: public base_b
{
public:
  virtual void on_call(derived_a1* pa1) { pa1->on_visit(this); }
  ... 
};

Теперь вызов типа pa->fn(pb), если pa указывает на derived_a1, а pb-на derived_b1, наконец, перейдет к derived_a1::on_visit(derived_b1*).

Шаблон посетителя-этоодно решение, которое реализует поведение двойной отправки. Может быть и несколько других решений. Термин двойная отправка сам по себе не дает никакого представления о решении, фактически это проблема, решение которой обеспечивается посетительским шаблоном.

В C# (4.0) можно использовать ключевое слово dynamic для реализации двойной отправки, в этом случае шаблон посетителя не требуется. Вот мое решение проблемы double-dispatch с использованием dynamic ключевое слово:

динамическая диспетчеризация относится к концепции диспетчеризации к методу, основанному на информации времени выполнения, в целом. Большинство систем OO (как в Java/C#/C++) обычно реализуют динамическую отправку с помощью методов virtual (независимо от того, являются ли все методы виртуальными, зависит от языка); это ограничивает их отправку в соответствии с одним аргументом метода (неявная ссылка на объект).

В общем случае вы можете захотеть отправить в соответствии с произвольным числом элементов. Двойной Например, Dispatch-это требование / возможность отправки в соответствии с двумя аргументами метода.

С другой стороны, шаблон посетителя являетсяреализацией множественной диспетчеризации вообще и, следовательно, двойной диспетчеризации в частности в таких системах ОО.

Двойная отправка-это техническая проблема, которая может, в зависимости от языка, решаться по-разному-некоторые языки поддерживают двойную отправку напрямую. Шаблон посетителя-это шаблон, который может быть использован для решения различных проблем. В случае C++ это наиболее частое (но не единственное) решение, используемое для двойной отправки, но оно не используется исключительно для этого, и оно может быть полезно даже в языках, которые поддерживают двойную отправку.

Из Википедии:

Шаблон посетителя имитирует двойную отправку на обычном объектно-ориентированном языке с одной отправкой, таком как Java, Smalltalk и C++.

Также из Википедии :

Описанная выше проблема может быть решена путем моделирования двойной отправки,например, с помощью шаблона посетителя.

Comments

    Ничего не найдено.