No tak se musím přiznat, že z toho až tak úplně nejsem moudrý nejsem.
Asi jsem dneska nějaký natvrdlý, ale není mi úplně jasné, jak přepsat
do Visitor patternu následující jednoduchý příkládek:
Mějme příklad "if podle typu parametru":
interface Data {
}
class A implements Data {
String name;
}
class B extends A {
int size;
}
class ServiceA {
void run() {
A a = ((Servisa)ctx.lookup("servisa")).callFunc(new A());
System.out.println(a);
}
}
class ServiceB {
void run() {
B b = (B) ((Servisa)ctx.lookup("servisa")).callFunc(new B());
System.out.println(b);
}
}
interface Servisa {
A callFunc(A result);
}
class ServisaImpl implements Servisa {
public A callFunc(A result) {
return new DalsiServisa().doSomething(result);
}
}
class DalsiServisa {
A doSomething(A result) {
//....
if (result instanceof B) { return new DelejFuncB().akce(result);}
else { return new DelejFuncA().akce(result);}
//.....
}
}
interface Delej {
A akce(A result);
}
class DelejFuncA implements Delej{
public A akce(A result) {ResultSet rs =
con.createStatement("select name from tabulka"); rs.next();
result.name = rs.getString("name"); return result;}
}
class DelejFuncB implements Delej {
public A akce(A AResult) { B result = (B)aResult; ResultSet rs =
con.createStatement("select name,size from tabulka"); rs.next();
result.name = rs.getString("name"); result.size = rs.getInt("size");
return result;}
}
****************
A teď k tomu přepisu - co je visitorem? DelejFuncA a DelejFuncB? A
Data má potom implementovat accept(Delej)? Servisa má pak mít dvě
metody a v každé vytvořit instanci Delej podle toho, co kdo má co
dělat? A to ještě máme jednoduchý příklad, kdy jako vstup jde Data. Co
když chci ona Data vytvořit?
A v čem mi to potom pomůže kromě toho, že if neřeším programově v
kódu, kde by to bylo IMHO logické, ale nechávám to na Javě, přičemž
musím všechny mezivýpočty delegovat do parametrů více metod, kdy musím
mít jednu každou pro každý hook)? Tady nejde o tom, aby se jeden
visitor vypořádal z různými daty, ale aby jeden generátor na základě
znalostí akceptora vygeneroval pro různé akceptory různě odekorovaná
typově tatáž data.
Dík za vysvětlení,
Dne 19. července 2010 14:55 Karel Tejnora <[email protected]> napsal(a):
> Visitor pattern.
>
> Evidentně budete zasahovat do kódu, takže místo přidávání and cp a boolean
> to udělat trochu jinak.
>
> (Tady se da udelat i extends ale to se provaze s implementaci)
>
> Extrahovat interface (IfaceA) ze současné struktury (StructA) - a přidat
> druhou strukturu (StructB) která implementuje tento interface také (může i
> rožšiřovat StructA).
>
> Interface bude mít navíc metodu jako "setResults(ServiceInterface
> serviceA)".
>
> A service bude mít selectResult(IfaceA obj) která zavolá
> Iface.setResults(this)
>
> StructA.setResults(ServiceInterface service)
> {
> service.selectResults(this); // v tomhle pripade uz "this" je plne znamy
> typ
> }
>
> StructB.setResults(ServiceInterface service)
> {
> service.selectResults(this); // v tomhle pripade uz "this" je plne znamy
> typ
> }
>
> no a konecne v ServiceInterface bude mit
>
> ServiceInterface.selectResult(Struct A) a
> ServiceInterface.selectResult(Struct B)
>
> Takhle nebudete mit zadny if else if else if a v budoucnu pokud pridate
> StructC D E F G H
> zasahnete kod ServiceInterface. Ono dokonce lze zdetit i ServiceInterface na
> ServiceIterfaceCDEF
>
> a v StructCDEF bude mit ServiceIterfaceCDEF - protoze Implementace zna sebe
> diky "this" tak to bude dal fungovat.
>
> Testovani: pokud se zavede boolean (N=2) nebo int (N) a to k tomu kazda
> dalsi stuktura (M) melo by se napsat NxM testu. Takhle 2xM. Tohle ma spis
> ukazat tu vyhodnost.
>
>
> Karel
>
> A je to refactoring safe. Coz v pripade booleanu nebo intu neni
>
> Naopak OOP bylo vymysleno tak aby se kod funkcni a odzkouseny pouzival znova
> a znova a znova.
>
>
>> d) pro omezení zbytečného výpočtu statistik v c) přidat do volání API
>> boolean (nebo raději int pro více možných stavů) parametr udávající,
>> zda výpočty volat či nikoli (rozhodování může to být řešeno dědičností
>> konkrétní datové struktury, ale to je pořád onen boolean či int a s
>> ním někde svázaný switch či kupa ifů).
>
>
--
Oto 'tapik' Buchta, [email protected], http://tapikuv.blogspot.com