Scegliere quale classe usare

di il
6 risposte

Scegliere quale classe usare

Vorrei farvi una domanda forse banale forse no, giudicate voi ma spero la prima.
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. Sono riuscito a fare tutto ma questa operazione mi ha portato a correggere più di una classe della mia WebApp.
Ecco la strategia che ho usato:

        boolean varDB = true;
        Nome nome;
        if(varDB){
            nome = new Nome1();
        }else {
            nome = new Nome2();
        }
        nome.esegui();
E’ possibile aggiungere una terza classe (Nome.java) come avevo ai primordi e “riempire” questa terza classe con tutto il contenuto di Nome1.java o Nome2.java a seconda della variabile del DB o chiedo troppo?
In pratica mi piacerebbe, in futuro, poter andare ad aggiungere Nome3.java, Nome4.java e andare a modificare solo Nome.java senza preoccuparmi di andare a correggere tutta la mia applicazione. In tutto il codice della mia WebApp vorrei lasciare:
Nome nome = new Nome();
Se serve posto un codice più completo.

6 Risposte

  • Re: Scegliere quale classe usare

    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).
  • Re: Scegliere quale classe usare

    Grazie mille!
  • Re: Scegliere quale classe usare

    SpringBoot e' un ""framework"" che implementa un sacco di cose ""interessanti"".

    MA NON E' la risposta ad un problema di ""modellazione"" in senso ""generale"".

    In questo caso, il problema e' PIU' GENERALE di una soluzione usando SpringBoot!

    La soluzione e' quella di utilizzare un "Design Pattern" (https://en.wikipedia.org/wiki/Software_design_patter).
    C'e' ne sono 2 possibili:

    1) Factory Method
    2) Builder.


    Notare che SpringBoot praticamente implementa il Design "Builder".
  • Re: Scegliere quale classe usare

    Grazie Migliorabile, la soluzione che ho trovato può bastare, ora preferisco concentrarmi su questo maledetto @Async (*) che non riesco a stoppare e chiudere qui questa esercitazione che mi sta portando via troppo tempo.

    (*) Ci sono dei limiti di attesa per l'output di una pagina web? Come edito questi limiti con Spring Boot 2?
  • Re: Scegliere quale classe usare

    iBaffiPro ha scritto:


    ora preferisco concentrarmi su questo maledetto @Async (*) che non riesco a stoppare e chiudere qui questa esercitazione che mi sta portando via troppo tempo.
    Concordo. In settimana sono stato impegnato su questioni lavorative, ti rispondo all'altra discussione appena posso, spero già nel weekend.
  • Re: Scegliere quale classe usare

    Tranquillo, quando hai tempo, ti ringrazio molto, sei sempre super disponibile.
Devi accedere o registrarti per scrivere nel forum
6 risposte