±¾½ÚÓ¦ÓÃÃüÁîģʽ£¬ÔÚJavaÖÐÄ£ÄâË«·ÖÅÉ¡£Àí½â±¾½Úºó£¬·ÃÎÊÕßģʽ(visitor
pattern)ÊÖµ½ÇÜÀ´¡£
1. µ¥·ÖÅÉ
·ÖÅÉ/ dispatchÊÇÖ¸ÈçºÎ¸øÒ»¸öÏûÏ¢°ó¶¨Æä·½·¨Ìå¡£Java¡¢C#µÈ½ö½öÖ§³Öµ¥·ÖÅÉ£¨singledispatch£©¶ø²»Ö§³ÖË«·ÖÅÉ(double
dispatch)¡£¡¾Ïà¹Ø¸ÅÄ²Î¿¼¡¶Éè¼ÆÄ£Ê½.5.11·ÃÎÊÕßģʽ¡·p223¡¿
¶ÔÓÚÏûÏ¢a.foo(b)£¬¼ÙÉèÓи¸ÀàX¼°ÆäÁ½¸ö×ÓÀàX1¡¢X2£¬aÉùÃ÷ΪXÀàÐͱäÁ¿£»Óи¸ÀàY¼°ÆäÁ½¸ö×ÓÀàY1¡¢Y2£¬bÉùÃ÷ΪYÀàÐͱäÁ¿£¬¶øÇÒX¡¢X1ºÍX2¶¼¸÷×Ô×¼±¸ÁËfoo(Y)¡¢foo(Y1)ºÍfoo(Y2)·½·¨£¬ÇëÎÊa.foo(b)½«Ö´Ðеķ½·¨ÌåÊÇ3*3=9¸ö·½·¨ÖеÄÄÄÒ»¸ö£¿
µ±Ç°Ö÷Á÷µÄÃæÏò¶ÔÏóÓïÑÔÈçC++¡¢Java¡¢C#µÈ£¬½ö½öÖ§³Öµ¥·ÖÅÉ£¨singledispatch£©¡£Àý³Ì3-18ÖУ¬Ä¿Ç°¿ÉÒÔ²»¹Üa.foo(b)ÖеIJÎÊýb£¬ÎÒÃǽö½ö¿´ÏûÏ¢a.m()ºÃÁË¡£¼Ù¶¨X¡¢X1ºÍX2¶¼¸÷×Ô×¼±¸ÁËm()£¬Ôòa.m()°´ÕÕaµÄʵ¼ÊÀàÐÍ°ó¶¨ÆäoverrideµÄ·½·¨Ì壬Õâ¾ÍÊÇÃæÏò¶ÔÏóÖеĶ¯Ì¬°ó¶¨¡£
ËùνµÄË«·ÖÅÉ£¬ÔòÊÇÏ£Íûa.foo(b)Äܹ»¢Ù°´ÕÕaµÄʵ¼ÊÀàÐÍ°ó¶¨ÆäoverrideµÄ·½·¨Ì壬¶øÇÒÄܹ»¢Ú°´ÕÕbµÄʵ¼ÊÀàÐÍ°ó¶¨ÆäÖØÔØµÄ·½·¨¼´foo(Y)¡¢foo(Y1)¡¢foo(Y2)ÖеÄÊʵ±·½·¨Ìå¡£ÏÔÈ»£¬Java²»Ö§³ÖºóÕß¡ª¡ª¼´²»Ö§³ÖË«·ÖÅÉ¡£JavaÔÚ±àÒëʱ£¬¾ÍΪfoo(b)°´ÕÕbµÄÉùÃ÷ÀàÐ;²Ì¬°ó¶¨ÁËfoo(Y)Õâ¸öµÄ·½·¨Ìå¡£JavaÖØÔØ·½·¨µÄÆ¥ÅäËã·¨£¬Çë²Î¿¼¡¾±à³Ìµ¼ÂÛ¡¤2.3.1¡¿¡£
Àý³Ì 3 18 µ¥·ÖÅÉ package method.command.doubleDispatch; import static tool.Print.*; public abstract class X{ public void m(){ pln(" X.m()"); } public void foo(X x){ p(" X.foo(X)-"); x.m(); } public void foo(X1 x1){ p(" X.foo(X1)-"); x1.m(); }// foo(X2 x2) ÂÔ }//×ÓÀàX1¡¢X2µÄ´úÂ룬ÂÔ package method.command.doubleDispatch; import tool.God; public class Test{ public static void Xµ¥·ÖÅÉ(){ X a = (X)God.create("3-18-X1"); X b = (X)God.create("3-18-X2"); a.m(); a.foo(b); } }
|
¼òµ¥Æð¼û£¬ÏûÏ¢a.foo(b)µÄÖÐa£¬bµÄÀàÐ;ùΪX¡£Ë«·ÖÅÉ(double dispatch)¼´ÔÚÑ¡ÔñÒ»¸ö·½·¨ÌåʱÐèÒª¸ù¾ÝÏûÏ¢½ÓÊÕÕßaºÍ²ÎÊýbÁ½ÕßµÄÔËÐÐʱÀàÐÍ(ʵ¼ÊÀàÐÍ)½øÐа󶨣¬JavabuÖ§³Ö¡£ÎªÁË˵Ã÷ÕâÒ»µã£¬ÉÏÃæµÄ´úÂëÖУ¬XÏԵñȽϹÖÒìµÄ°üº¬ÁËfoo(X)¡¢foo(X1)¡¢foo(X2)·½·¨(¸¸ÀàXÒÀÀµÆä×ÓÀà)£¬¶øÇÒ×ÓÀàX1¡¢X2µÄoverrideÁËÖØÔØµÄfoo()·½·¨´úÂë¡£
Test.Xµ¥·ÖÅÉ() µÄÔËÐнá¹û£º
X1.m() // ¶¯Ì¬°ó¶¨ X1.foo(X)-X2.m() // ¶¯Ì¬°ó¶¨X1µÄfoo£¬¶ø¾²Ì¬°ó¶¨foo(X). |
ÄÇô£¬b.foo(a);µÄÔËÐнá¹û£ºX2.foo(X)-X1.m()
Èç¹û¶Ô¸ÄдµÄ¶¯Ì¬°ó¶¨ºÍÖØÔØµÄ¾²Ì¬°ó¶¨£¬ÒѾÇå³þÁË£¬Ò²¼´Çå³þµØÖªµÀ£ºJavaÖ§³Öµ¥·ÖÅɶø²»Ö§³ÖË«·ÖÅÉ£¬ÏÂÃæ¶ÔÓ¦µØ±àдY¡¢Y1ºÍY2½ö±£Áô¸÷×Ô×¼±¸µÄm()£¬¶øYϵÁÐÖÐɾ³ý¸÷ÖÖfoo·½·¨£¬ÔÚOverloadFooÀàÖÐרעÈçºÎÄ£ÄâË«·ÖÅÉ¡£
package method.command.doubleDispatch; import static tool.Print.*; public class Y{ public void m(){ pln(" Y.m()"); } } |
package method.command.doubleDispatch; import static tool.Print.*; public class Y1 extends Y{ @Override public void m(){ pln("Y1.m()"); } } |
package method.command.doubleDispatch; import static tool.Print.*; /** * OverloadFoo.java. * * @author yqj2065 * @version 0.1 */ public class OverloadFoo{ public void foo(Y y) { y.m();pln("foo(Y)"); } public void foo(Y1 y){ y.m();pln("foo(Y1)");} public void foo(Y2 y){ y.m();pln("foo(Y2)");} /** * (Run-Time Type Identification¡¢RTTI */ public void foo_RTTI(Y y){ if(y instanceof Y1){ pln("foo(Y1)"); }else if(y instanceof Y2){ pln("foo(Y2)"); }else{ pln("foo(Y)"); } } } |
JavaÖпÉÒÔʹÓÃÔËÐÐʱÀàÐÍʶ±ð(Run-Time TypeIdentification¡¢RTTI)¼¼Êõ¼´Ê¹Óùؼü×ÖinstanceofÅжÏʵ¼ÊÀàÐÍ¡£Òò¶ø£¬Ò»¸öȨÒËÖ®¼ÆÊÇɾ³ýÈý¸öÖØÔØµÄfoo()·½·¨£¬¶ø±àд·½·¨foo_RTTI
(Y )¡£ËäÈ»foo_RTTI (Y) ´úÂë¼ò½à£¬µ«ÊÇ£¬Ê¹Ó÷ÖÖ§Óï¾ä²»¹»ÓÅÑÅ¡£
Èç¹ûµ½´¦Ê¹ÓÃif-elseµÄ»°£¬ºÜ¶àģʽ¾ÍʧҵÁË¡£
2.ÃüÁîÄ£Ê½Çø·ÖÖØÔØµÄ·½·¨
¡¾±à³Ìµ¼ÂÛ¡¤2.3.1¡¿ ÖÐ˵Ã÷£º¡°ÖØÔØÒ»¸ö·½·¨£¬ÕæÕý×öµÄÊÂÇéÊǶ¨ÒåÁËÈô¸É²»Í¬µÄ·½·¨£¬²»¹ý¡®ÅöÇÉ¡¯Ê¹ÓÃÁËÏàͬµÄ·½·¨Ãû¡±¡£
µ÷ÓÃfoo(Y)µÄÄ£¿éÈçTest£¬ÔÚËü¿´À´ÖØÔØfoo(X)¡¢foo(X1)¡¢foo(X2)Ò²ºÃ£¬²»Í¬ÃûµÄfooX()¡¢fooX1()¡¢fooX2()Ò²ºÃ£¬TestÏ£Íû½øÐÐͳһµÄµ÷Ó᪡ªÎÞÊÓ±»µ÷µÄ·½·¨Ãû£¬ÎÒÃÇ¿ÉÒÔ²ÉÓÃÃüÁîģʽ¡£
package method.command.doubleDispatch; public abstract class Command{ OverloadFoo handler = new OverloadFoo(); public abstract void foo(Y y);//±ä»¯£ºÖ´ÐÐÕßÒÑÖªOverloadFoo } |
package method.command.doubleDispatch; public class FooY1 extends Command { @Override public void foo(Y y) { handler.foo((Y1)y); } }//FooYºÍ FooY2ÂÔ |
Õâ¸öCommandºÍ3.4 ÃüÁîģʽ(5.2)Öмòµ¥µÄCommand½Ó¿ÚÓÐЩССµÄ½ø²½£ºÃüÁîµÄÖ´ÐÐÕßÒÑ֪ΪOverloadFoo(ÒòΪËü°üÀ¨ÁË3¸öÖØÔØµÄfoo·½·¨)£»³éÏó·½·¨foo´øÓвÎÊý¡£
CommandµÄ×ÓÀàFooY1£¬Ö¸Ã÷Ö´ÐÐÕßµ÷ÓÃÖØÔØµÄfoo(Y1)·½·¨¡£
public static void Ä£ÄâË«·ÖÅÉ(){ Y y = (Y)God.create("3-18-Y");//Y1¶ÔÏó Command cmd = new FooY(); cmd.foo(y); cmd = new FooY1(); cmd.foo(y); cmd = new FooY2();//ÈÎÎñ²»¿ÉÖ´ÐÐ //cmd.foo(y); } |
ÏÖÔÚ£¬´´½¨Ò»¸öY¶ÔÏó(ʵ¼ÊÀàÐÍY1)ºó£¬°´ÕÕ²»Í¬µÄÃüÁ²âÊÔ½á¹û£º
Y1.m() foo(Y) Y1.m() foo(Y1) |
ÃüÁîģʽ£¬Ê¹µÃÓû§ÀàTestÎÞÊÓ±»µ÷µÄ·½·¨Ãû£¬Ï´ïͳһµÄÃüÁîfoo(y)£»¶øÖ´ÐÐÕß°´ÕÕÃüÁî¶ÔÏóµÄ²»Í¬£¬Ö´Ðв»Í¬µÄ·½·¨Ì塪¡ªÕâÀï¾Í½«ÖØÔصķ½·¨Çø·Ö¿ªÀ´ÁË¡£

ͼ1 Ó¦ÓÃÃüÁîģʽ
3.ºÏ²¢Àà²ã´Î
ÉÏͼÖÐÓÐÁ½¸öÀà²ã´ÎYºÍCommand£¬Í¼ÐÎÏԵñȽϸ´ÔÓ¡£ÎÒÃÇ·¢ÏÖCommandµÄÆÕÊÊÃüÁîfoo(Y y)ÔÚÆä×ÓÀàFooY1ÖеĴúÂëΪ£º
@Override public void foo(Y y) { handler.foo((Y1)y); } |
ÎÒÃÇÈçºÎÀûÓÃJavaµÄ¶à̬ÐÔ±ÜÃâÕâÖÖÖ¸¶¨ÐÔµÄÇ¿ÖÆÀàÐÍת»»ÄØ£¿Òªµã¾ÍÊÇÃüÁîµÄÖ´ÐÐÕß²»ÔÚÊǹ̶¨µÄ
OverloadFoo handler = new OverloadFoo();
¶øÊÇFooY1×Ô¼º¡ª¡ªÃüÁîÖ´ÐÐÕß½«ÊÇY1ºÍY2£¡
ÏÖÔÚ£¬¿ªÆôZϵÁС£
YϵÁÐʱµÄ Command¶ÔÓ¦½Ó¿ÚFoo£¬ÆÕÊÊÃüÁîfoo(Y y)¶ÔӦΪwi²ÎÊýµÄhandleFoo()¡£
package method.command.doubleDispatch; public interface Foo{ public void handleFoo(); } |
ÓëXºÍY¶ÔÓ¦µÄZ£¬ÓëX²»Í¬Ö®´¦Îªfoo(Foo )£¡
ZµÄÀà²ã´Î³ÉΪCommand/FooµÄ×ÓÀàÐÍ¡£Z implements FooʹµÃZµÄ×ÓÀà×Ô¶¯³ÉΪFooµÄ×ÓÀàÐÍ£¬£¨ÆäʵZ±¾Éí²»ÐèÒª³ÉΪ
FooµÄ×ÓÀàÐÍ£¬Äã¿ÉÒÔ½«ZµÄËùÓÐ×ÓÀàZ1¡¢Z2 implements Foo£©
package method.command.doubleDispatch; import static tool.Print.*; public abstract class Z implements Foo{ public void m(){ pln(" Z.m()"); } public void foo(Foo z ){//ʾÀý´úÂ룬¿ÉÒÔΪ¿Õ·½·¨Ìå p(" Z.foo(Foo)-"); this.m(); } //@Override public void handleFoo(){} //¿ÉÓпÉÎÞ } |
ÏÖÔÚ£¬Z1µÄ´úÂëÈçÏ£º
package method.command.doubleDispatch; import static tool.Print.*; public class Z1 extends Z { @Override public void m(){ pln(" Z1.m()"); } /*ÊÂʵÉÏ£¬Òâζ×ÅÖØÔØfoo(Z1)*/ @Override public void foo(Foo z ){ p("Z1."); z.handleFoo();//Ö´ÐÐÕßz¶¯Ì¬°ó¶¨ this.m(); } private void foo(){ p("foo(Z1)-"); } @Override public void handleFoo(){ this.foo(); } } |
package method.command.doubleDispatch; import tool.God; public class Test{ public static void ZË«·ÖÅÉ(){ Z z1 = (Z)God.create("3-18-Z1");//Z1¶ÔÏó Z z2 = (Z)God.create("3-18-Z2");//Z1¶ÔÏó z1.foo(z1); z1.foo(z2); z2.foo(z1); z2.foo(z2); } } |
²âÊÔ½á¹û£º
Z1.foo(Z1)- Z1.m() Z1.foo(Z2)- Z1.m() Z2.foo(Z1)- Z2.m() Z2.foo(Z2)- Z2.m() |
¶ÔÓÚÏûÏ¢a.foo(b)£¬¼ÙÉèa¡¢bÉùÃ÷ΪZÀàÐͱäÁ¿£¬Ä¿Ç°ÎÒÃÇÄ£ÄâÁËË«·ÖÅÉDouble Dispatch¡£

ͼ2 ¼ò½àµÄË«·ÖÅɽṹ
ÕâÊÇÒ»ÖÖÓÐÓõĽṹ£¬ÎÒÃÇ¿ÉÒÔ³ÆÖ®ÎªË«·ÖÅÉģʽ¡££¬ÊDz»ÊǺÜÅ£±Æ£¿
²»¹ý£¬ÓÐЩÌÖÈËÏӵļһËûÃǸüÅ£±Æ£¬ËûÃÇÔÚ×Ô¼ºµÄÊéÖУ¬°ÑË«·ÖÅÉģʽ³ÆÎª·ÃÎÊÕßģʽ£¡
Äã¿ÉÒÔÐÞ¸ÄÉÏÊö´úÂ룬ʹµÃÏûÏ¢a.foo(b)£¬ÆäÖÐaÉùÃ÷ΪXÀàÐͱäÁ¿¡¢bÉùÃ÷ΪZÀàÐͱäÁ¿¡£
°´ÕÕÄ£ÄâµÄË«·ÖÅÉÄ£ÐÍ£¬»á³ÉΪ2*2µÄ±íʾ·½Ê½£¬£¬ÕâÊÇÁ½¸ö²½ÖèµÄµþ¼Ó¶øÐγÉ4¸ö´¦ÀíÁ÷³Ì¡£Ã»ÓÐË«·ÖÅÉ»úÖÆ£¬ÄÇÃ´Çø·ÖÖØÔØ²Ù×÷ÊDz»¿ÉÐе쬶ÔÓÚX1ºÍX2µÄ¶ÔÏó£¬ÐèÒª·½·¨fooZ1(Z1)ºÍfooZ2(Z2)£¬Óëa.foo(b)¶ÔÓ¦µÄ£¬ÓÐ4¸ö·½·¨Ìå¡£
|