Разница между посетителем pattern & Double Dispatch
Я читаю о шаблоне посетителя, и он выглядит так же, как двойная отправка. Есть ли какая-то разница между ними?
Делать два термина означает одно и то же.
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++ это наиболее частое (но не единственное) решение, используемое для двойной отправки, но оно не используется исключительно для этого, и оно может быть полезно даже в языках, которые поддерживают двойную отправку.
Comments