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.