Newsgroup: it.comp.java
Titolo: Strategia da seguire per eliminare codice comune

Ciao al gruppo,
ho un'applicazione J2EE che usa Struts  + EJB. Le Action invocano
metodi sugli EJB remoti tramite un'interfaccia di delegazione, esempio:
public ActionForward execute(...)
{
  // codice comune
  newClient = getOldDelegate().getClientSummary();
  // codice comune
}
OldDelegate ha molti metodi del tipo:
public class OldDelegate implements IDelegate
{
  //......
  public ClientSummary getClientSummary(String clientID)
  {
   return getClientDataBean().getClientSummary(clientID);
  }
  // .....
}
Tutte le classi hanno quel codice comune, che opera controlli di vario
tipo, vorrei spostarlo in un punto comune. Ho operato in questo modo:
1) creato un NewDelegator con un metodo pubblico e uno astratto:
abstract public class NewDelegator
{
  public Object executeDelegateMethod(Object arg)
  {
    // codice comune
    obj = executeDelegateAction(arg);
    // codice comune
    return obj;
  }
  abstract protected Object executeDelegateAction(Object arg);
}
2) per ogni metodo di OldDelegate ho creato una classe che estende
NewDelegator:
public class ClientSummaryRetriever extends NewDelegator
{
  protected Object executeDelegateAction(Object clientID)
  {
    return getClientDataBean().getClientSummary(clientID);
  }
}
3) Sostituito il metodo di OldDelegate con:
public ClientSummary getClientSummary(String clientID)
{
 ClientSummaryRetriever csd = new ClientSummaryRetriever();
 return (ClientSummary) csd.executeDelegateMethod(clientID);
}
Credo di aver seguito un pattern detto Strategy, correggetemi se
sbaglio.
Un mio collega ha da obiettare che in questo modo genereremo una
proliferazione di classi e che il codice ottenuto sara' poco
efficiente. Non gli piace questa idea di avere molte classi con un
metodo solo.
Egli propone di utilizzare un wrapper, ossia una classe che implementa
IDelegate, che usi la reflection per invocare il corrispondente metodo
su OldDelegate:
public class WrapOldDelegate implements IDelegate
{
  public ClientSummary getClientSummary(String clientID)
  {
   invokeOldDelegateMethod("getClientSummary", new String[]{clientID});
  }
  private Object invokeOldDelegateMethod(String methodName, Object[]
argz)
  {
   // codice comune
   // codice che invoca il metodo su OldDelegate utilizzando la
reflection
   // codice comune
  }
}
Sostiene che in questo modo il codice sarebbe assai piu' gestibile, non
dovendo creare nuove classi ma solo aggiornare il codice delle vecchie.
Voi, che ne pensate?
TREMALNAIK

 
Ho letto quello che hai scritto molto velocemente, quindi dovrei 
pensarci un pò sù.
Io cmq, quando ho un metodo con questa struttura:
//codice comune
//codice specifico
//codice comune
Preferisco usare il pattern Decorator.
Il decorator è una classe che fà roba comune e che "circonda" oggetti 
che fanno roba specifica.
Velocemente, ti dico some lo implemento.
Tutti i miei oggetti avrenno un interfaccia comune.
Questa interfaccia avrà il metodo faiQualcheCosa() che ha codice comune.
Negli oggetti specifici questo metodo implementa solo il codice spefico.
Il mio decorator implementa la stessa classe, e contiene uno degli 
oggetti specifici, diciamo che lo chiamiamo "decorato".
Tutti i metodi saranno semplicemente del tipo:
	metodo(){
	   decorato.metodo();
	}
Mentre i metodi di cui hai bisogno di codice incomune saranno:
	metodo(){
		//codice comune
		decorato.metodo();
		//codice comune
	}
Per usare un decorator basta che invece di insenziare un oggetto 
specifico con new oggettoSpecifico() fai: new Decorator(new 
OggettoSpecifico).
Puoi usi il decorato come se fosse il tuo oggetto.
Ovviamente la cosa richiede che i tuoi oggetti abbiamo tutti la stessa 
interfaccia.
Scusami della spiegazione approssimativa e veloce, ma vado di fretta.
Buon lavoro
Delvy

 pensarci un pò sù.
grazie per la risposta. In effetti la mia soluzione non e' molto
diversa dalla tua. 
TREMALNAIK