iBaffiPro ha scritto:
Ho un’interfaccia con un certo numero di metodi (NomeInterface.java) e 2 classi che implementano questa interfaccia (Nome1.java e Nome2.java). Il mio obiettivo iniziale era inserire nel codice del mio programma una condizione (una semplice if per intenderci) che in base al valore di una certa variabile presa dal DB l’utente possa scegliere quale classe usare.
Con Spring/Boot si può fare questa cosa 10 volte meglio ... e SENZA if. A condizione di conoscere a priori dei valori da usare come "chiavi" per rintracciare la strategia da usare (tipicamente dei String).
Si fa una interfaccia di "strategia", che ha tutti i metodi che servono. Più magari un es. getKey() che dà una chiave (univoca, ragionevolmente).
public interface MyStrategy {
// metodi .....
String getKey();
}
Poi puoi fare N classi di implementazione, da definire come bean Spring, cioè ad esempio applicando @Component.
@Component
public class MyStrategy1Impl implements MyStrategy {
// ....
@Override
public String getKey() {
return "S1";
}
}
Poi fai un service del tipo (abbozzato):
@Service
public class MyStrategyService {
private final Map<String, MyStrategy> strategiesMap;
public MyStrategyService(List<MyStrategy> allStrategies) {
strategiesMap = new HashMap<>();
for (MyStrategy strategy : allStrategies) {
strategiesMap.put(strategy.getKey(), strategy);
}
}
public MyStrategy getMyStrategy(String key) {
MyStrategy myStrategy = strategiesMap.get(key);
if (myStrategy == null) {
// lancia eccezione, non c'è la strategia richiesta
}
return myStrategy;
}
}
Attenzione, qui viene la parte importante:
quando Spring crea l'oggetto bean MyStrategyService, "inietta" in automatico nel suo costruttore una lista con TUTTI i bean Spring che implementano MyStrategy. Poi MyStrategyService si tiene una mappa chiave --> bean-strategia.
Se da qualche parte (es. in un controller o altro service) fai
@Autowired MyStrategyService myStrategyService;
//...
MyStrategy selectedStrategy = myStrategyService.getMyStrategy(unaChiave); // unaChiave es. "S1"
Ottieni il bean che implementa quella strategia, ovviamente "vedendolo" solo con il tipo della interfaccia (che in generale dovrebbe essere più che sufficiente).
Se aggiungi altre classi di implementazione, le puoi chiamare come vuoi (il nome della classe non inficia sulla logica) e in qualunque package vuoi. Purché ovviamente vengano "pescate" dal
component scanning di Spring.
Nessun if, nessuna altra logica da aggiornare (nemmeno in MyStrategyService).