Ciao, in un progetto su cui sto lavorando sto provando un approccio che non avevo mai usato in passato per le liste di oggetti java, immaginate che di avere una lista tipo:
List<SomeObject> list = new ArrayList<SomeObject>();
Se volessi estrarre dalla lista tutti gli elementi aventi un certo campo valorizzato ad un dato valore, ovvero fare un filtro, farei:
class SomeObject {
public static List<SomeObject> filterByField(List<SomeObject> input, String value) {
// ciclo la lista input e restituisco una lista nuova con gli oggetti che hanno field=value
}
}
usato così:
List<SomeObject> all = new ArrayList<SomeObject>();
List<SomeObject> filtered = SomeObject.filterByField(all, "someValue");
Il fatto però di avere metodi statici ‘helper’ dentro SomeObject
per
aggiungere funzionalità ad una lista non mi piace molto… ho provato
invece a wrappare List
e a spostare il metodo filerByValue
da
SomeObject
alla nuova classe SomeObjects
:
class SomeObjects extends ArrayList<SomeObject> {
public SomeObjects filterByField(String value){
// filtro ciclando gli elementi in this e restituisco una nuova istanza di SomeObjects
}
}
Il codice di utilizzo quindi diventa:
SomeObjects all = new SomeObjects();
SomeObjects filtered = all.filterByField("someValue");
Che mi pare molto più pulito e leggible, che ve ne pare?
So che non è un gran cambiamento, ma ho un parametro in meno per ogni
filterByXXX
che desidero aggiungere e ogni metodo è nel posto che gli
compete, ovvero i medoti per filtrare una lista stanno nella lista e non
come metodi helper dell’oggetto contenuto.
Un’altro punto dove questo approccio è utile è nei Dao che wrappano funzionalità di IBatis o Hibernate, dove si trova spesso codice di questo tipo per prevenire il ritorno di liste nulle:
List<SomeObject> result = new ArrayList<SomeObject>();
result.addAll( ...queryForList("your query", param));
return result;
Con i wrapper possiamo scrivere un costruttore ad hoc, che prende una
lista in input e fa addAll(...)
solo se è diversa da null
:
public class SomeObjects extends ArrayList<SomeObject> {
public SomeObjects () {}
public SomeObjects (Collection<SomeObject> c) {
if (c!=null) addAll(c);
}
}
E il codice di utilizzo diventa magicamente:
return new SomeObjects(...queryForList("your query", param));
Fatemi sapere che ne pensate, io mi sto trovando bene con questo approccio.
Paolo Donà si occupa di sviluppo web in
Java e Ruby, sviluppo progetti su commessa e formazione/training. Potete
contattarlo via mail o leggere il suo blog
aziendale o
personale.