Nejprve jak psal Kamil jde o to co preferujete. Paradoxne jsem vcera
zkusil postup s "prepinacem" typu Enum a treba na muj vkus mi to prinasi
vice problemu (NPE, vice testu) nez pozitiv a socialnich jistot :-) ale
je to o nazoru. Teda moje reseni je na zpusob:
interface Data
{
/* stejne by jste resil "int getCoJsem()" */
public abstract void accept(ServisaA visitor);
}
class A implements Data {
String name;
...
/* casto implementuju copy constructor */
public A(A a)
{ this.name = a.name }
public void accept(ServicaA visitor) {
visitor.selectData(this); // this je typu class A
}
}
class B extends A {
int size;
...
/* casto implementuju copy constructor */
public B(A a)
{ super(a) }
public B(B b)
{
super(b);
this.size = size;
}
public void accept(ServicaA visitor) {
visitor.selectDataWithCounts(this); // this je typu class B
/* tady je zamysleni jestli vyhovuje pouziti pretizenych metod na zaklade typu
parameteru ci nikoliv
alternativne: */
visitor.selectData(this); // this je typu class B
}
}
class ServisaA
{
public Servisa lookupService()
{ return ((Servisa)ctx.lookup("servisa")); }
public void selectData(A data)
{
ResultSet rs = con.createStatement("select name from
tabulka"); rs.next();
data.name = rs.getString("name");
}
public void selectDataWithCounts(B data)
{
ResultSet rs = con.createStatement("select name,size from
tabulka"); rs.next();
data.name = rs.getString("name"); data.size = rs.getInt("size");
/* ale kdyby bylo size treba "select count(*) from tabulka" tak: */
selectData(data);
ResultSet rs = con.createStatement("select count(*) from tabulka");
rs.next();
data.size = rs.getInt(1);
}
/* ted to je zase podle vkusu, nemusi to byt (visit=selectData) */
public void selectData(Data data)
{
data.accept(this);
}
}
ted:
class UplneJinaServisa
{
public run()
{
/* ve factory se vyrabi to ci oto, takze 5minut
vyrabite pouze A, pak si jednou vyrobite B a zase pet minut A, nebo
factory muzu vyrabet 1000 A pak 1 B a pak 1000 A ... */
Data data = DataFactory.newInstance(<Nejake paramtery
ktere muzou rikat co se vyrobi>);
... furt stejnej kod co vsude byl ...
... i volani 100 service ktera vubec nic nevi o
nejakem A nebo B ...
... a nekde hluboko ... bud a)
/* ze servisaA.selectData(data); se stane */
data.accept(servisaA);
/* nebo protoze mame selectData(data) tak ten radek
zustane */
servisaA.selectData(data);
}
}
takze celej slozitej a uz odzkousenej kod zustal stejny. Tusim, ze pak
compilator je schopen ty volani nahradit skoc sem skoc tam a pak zase
trosku jinam. Vyhoda je ze kdyz pridate C tak cely kod zustane stejny
pouze neco pribude na ServiceA, takze vam projdou vsechny testy pro A i
B.
ano rad nechavam hodne veci na kompilatoru.