Différence entre le motif du visiteur et le double envoi

Je suis en train de lire à propos de la structure des visiteurs, et cela ressemble à Double Dispatch. Y a-t-il une différence entre les deux. Faire les deux termes signifie la même chose.

référence: http://www.vincehuston.org/dp/visitor.html

    En bref

    elles proviennent de conceptualisations différentes qui, dans certaines langues où la double dissortingbution n’est pas prise en charge de manière native, conduisent au modèle de visiteur comme moyen de concaténer deux envois uniques (ou plus) afin d’avoir un substitut multi-envoi.

    En long

    L’idée de la répartition multiple est – essentiellement – de permettre un appel comme

    void fn(virtual base_a*, virtual base_b*); (note: pas en tant que membre de la classe: ce n’est pas C ++!)

    qui peut être remplacé comme

     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*); 

    pour que, en appelant

     fn(pa, pb) 

    l’appel est redirigé vers le remplacement qui correspond au type d’exécution réel de pa et pb . (Vous pouvez généraliser cela à n’importe quel nombre de parameters)

    Dans des langages tels que C ++, C #, Java, ce mécanisme n’existe pas et la dissortingbution de type runtime fonctionne essentiellement avec un seul paramètre (qui, étant un seul, est implicite dans la fonction en rendant la fonction membre de la classe):

    en d’autres termes, le pseudo-code

     void fn(virtual base_a*, base_b*) 

    devient le (vrai C ++)

     class base_a { public: virtual void fn(base_b*); } 

    Notez qu’ici, il n’y a plus de virtual devant base_b , qui est désormais statique. Un appel comme

    pa->fn(pb) si pa pointe sur un déroulé_a2 et si pb sur abstract_b1 sera envoyé sur dériv_a2 :: fn (base_b *), peu importe s’il y a un dériv_a2 :: fn (dérivée_b1 *): le run Le type -time de l’object indiqué par pb n’est pas pris en compte.

    L’idée du visiteur est d’appeler la dissortingbution virtuelle d’un object qui appelle (éventuellement) la dissortingbution virtuelle d’un autre:

     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); } ... }; 

    maintenant, un appel tel que pa->fn(pb) , si pa pointe sur deriv_a1 et pb sur deriv_b1, ira finalement dans derived_a1::on_visit(derived_b1*) .

    Le pattern visiteur est une solution qui implémente le comportement de double dispatch. Il peut aussi y avoir plusieurs autres solutions. Le terme double dispatch lui-même ne donne aucune idée de la solution, en fait, il s’agit d’un problème dont la solution est fournie par le comportement des visiteurs .

    En C # (4.0), on pourrait utiliser dynamic mot-clé dynamic pour implémenter la double expédition, auquel cas le modèle de visiteur n’est pas requirejs. Voici ma solution pour résoudre le problème à l’aide de mots clés dynamic :

    • Avantages et inconvénients du mot clé “dynamic” C # 4.0?

    Dynamic Dispatch fait référence au concept de dissortingbution à une méthode basée sur des informations d’exécution, en général. La plupart des systèmes OO (comme en Java / C # / C ++) implémentent généralement la répartition dynamic via virtual méthodes virtual (que toutes les méthodes soient virtuelles ou non du langage); cela les limite à l’envoi en fonction d’un seul argument de méthode (la référence d’object implicite).

    En général, vous pourriez vouloir expédier selon un nombre arbitraire d’éléments. Double Dispatch, par exemple, est la condition / capacité à expédier selon deux arguments de la méthode.

    D’autre part, le Pattern Visiteur est une implémentation de Multi Dispatch en général et donc Double Dispatch en particulier dans de tels systèmes OO.

    Le double envoi est un problème technique qui, selon la langue, peut être résolu de différentes manières: certaines langues prennent directement en charge la double envoi. Le modèle de visiteur est un modèle qui peut être utilisé pour résoudre différents problèmes. Dans le cas de C ++, c’est la solution la plus fréquente (mais pas la seule) utilisée pour la double expédition, mais elle n’est pas utilisée exclusivement pour cela, et elle peut être utile même dans les langages prenant en charge la double expédition.

    De Wikipedia :

    Le modèle de visiteur simule une double répartition dans un langage orienté object à envoi unique, tel que Java, Smalltalk et C ++.

    Aussi de Wikipedia :

    Le problème décrit ci-dessus peut être résolu en simulant une double expédition, par exemple en utilisant un modèle de visiteur.