//Ilustracija mehanizma "double dispatch" koji Visitor implementira //Poreklo termina "double dispatch" //Naime,OO poruke manifestuju "single dispatch" <=> //operacija koja se izvrsava zavisi od:vrste zahteva, tipa primaoca //Postoje jezici koji direktno podrzavajau "double dispatch" (CLOS). //Postoje jezici poput Java , C++ koji podrzavaju "single dispatch" //Jezici koji podrzavaju double dispatch ili multi dispatch umanjuju //potrebu za Visitor design pattern-om. //"double dispatch" <=>operacija koja se izvrsava zavisi od : // vrste zahteva,tipa DVA primaoca //Operacija accept karakteristicna za Visitor DP je double dispatch. //Zavisi od tipa Posetioca i tipa Elementa,omogucavajuci posetiocima da //zahtevaju razlicite operacije za svaku klasu elementa. //virtual ? Java? // virtual =odlaze razresavanje do vremena izvrsavanja programa // Ako zelimo da deklarisemo ovakvu "funkciju": // void process( virtual Base object1, virtual Base object2 ) // koja primenjuje algoritam zasnovan nad tipovima 2 objekta koja poticu // iz jedne hijerarhije, onda postoji problem sto kljucna rec // "virtual" moze da se ne upotrebi za zahtev dinamickog vezivanja //objekta koji se prosledjuje. // Konkretno, kada se pozove process1() nad prvim objektom, // njegov tip, npr. A, B ili C postaje "poznat" za vreme izvrsavanja, // ali je tip drugog objekta, virtual Base, jos uvek nepoznat. // Tada se process2() poziva nad drugim // objektom, i identitet (samim tim i tip) prvog objekta (this) se prosledjuje // kao argument. //Tok kontrole se sada usmerava ka onom mestu //gde je poznat tip oba objekta(i , naravno, identitet oba objekta) . //Umesto statickog vezivanja operacija u interfejs Element,onda //izrzavajuci se u terminima dijagram prikaza za Visitor DP,moguce je "ucvrstiti" //operacije u Visitor-u,i upotrebiti Accept koji bi obavio vezivanje u vreme izvrsavanja, //sto je i potrebno. //Prosirivanje interfejsa Element dobija se dodavanjem nove potklase klase //Visitor, umesto mnogo novih potklasa klase Element. public class VisitorSingle { interface Base { void process1( Base secondObject ); void process2( A firstObject ); void process2( B firstObject ); void process2( C firstObject ); } static class A implements Base { public void process1( Base drugi ) { drugi.process2( this ); } /* Dakle, kada se pozove process1() nad prvim objektom, njegov tip, npr. A, B ili C postaje "poznat" za vreme izvrsavanja. Potom se process2() poziva nad drugim objektom, i identitet (samim tim i tip) prvog objekta (this) se prosledjuje kao argument. */ public void process2( A prvi ) { System.out.println( "prvi A, drugi jeste A" ); } public void process2( B prvi ) { System.out.println( "prvi B, drugi jeste A" ); } public void process2( C prvi ) { System.out.println( "prvi C, drugi jeste A" ); } } static class B implements Base { public void process1( Base drugi ) { drugi.process2( this ); } public void process2( A prvi ) { System.out.println( "prvi A, drugi jeste B" ); } public void process2( B prvi ) { System.out.println( "prvi B, drugi jeste B" ); } public void process2( C prvi ) { System.out.println( "prvi C, drugi jeste B" ); } } static class C implements Base { public void process1( Base drugi ) { drugi.process2( this ); } public void process2( A prvi ) { System.out.println( "prvi A, drugi jeste C" ); } public void process2( B prvi ) { System.out.println( "prvi B, drugi jeste C" ); } public void process2( C prvi ) { System.out.println( "prvi C, drugi jeste C" ); } } public static void main( String[] args ) { Base niz[] = { new C(), new A(), new B() }; for (int i=0; i < niz.length; i++) for (int j=0; j < 3; j++) niz[i].process1( niz[j] ); }}