CodeGym /Java Blog /Random-IT /Pattern e Singleton in Java
John Squirrels
Livello 41
San Francisco

Pattern e Singleton in Java

Pubblicato nel gruppo Random-IT
Questo articolo è rivolto a chiunque, per la prima volta, stia incontrando il concetto di design pattern, abbia sentito il termine singleton o abbia in qualche modo implementato il pattern singleton ma non abbia capito cosa stava succedendo. Benvenuto! Gli studenti di CodeGym incontrano i modelli di progettazione per la prima volta al livello 15, quando il capitano chiede loro inaspettatamente di "rafforzare" la loro comprensione implementando il modello Java Singleton con un'implementazione pigra. Gli studenti che sentono parlare del modello singleton per la prima volta si pongono immediatamente molte domande: cosa diavolo è un modello di progettazione? Perchè ne abbiamo bisogno? Cos'è un singleton ? E infine, cos'è l'implementazione pigra? Rispondiamo a queste domande in ordine.

Cosa diavolo è un modello di design?

Credo che un po' di storia serva per rispondere a questa domanda con la migliore comprensione. Ci sono quattro famosi autori di programmazione (Erich Gamma, John Vlissides, Ralph Johnson e Richard Helm) che hanno avuto un'idea interessante. Hanno notato che lo sviluppo del software spesso richiedeva loro di risolvere approssimativamente gli stessi problemi e scrivere codice strutturato nello stesso modo. Così hanno deciso di descrivere modelli tipici che spesso devono essere utilizzati nella programmazione orientata agli oggetti. Il loro libro è stato pubblicato nel 1994 con il titolo Design Patterns: Elements of Reusable Object-Oriented Software. Il nome del libro si è rivelato troppo lungo e la gente ha cominciato a chiamarlo semplicemente il libro della Banda dei Quattro. La prima edizione comprendeva 23 modelli. Successivamente, sono state scoperte dozzine di altri modelli.
Un modello di progettazione è una soluzione standardizzata a un problema comune.
E il modello singleton è solo uno di questi.

Perché abbiamo bisogno di modelli di progettazione?

Puoi programmare senza conoscere schemi: dopotutto, al livello 15, hai già scritto centinaia di mini-programmi su CodeGym senza nemmeno sapere che esistono. Ciò suggerisce che i modelli di progettazione sono una sorta di strumento il cui utilizzo distingue il maestro dall'amatore: i modelli di progettazione descrivono come risolvere correttamente un problema tipico. Ciò significa che conoscere i modelli ti fa risparmiare tempo. In questo modo, sono simili agli algoritmi. Ad esempio, potresti creare il tuo algoritmo di ordinamento con blackjack e numerie dedicare molto tempo a farlo, oppure potresti implementarne uno che è stato compreso e descritto per molto tempo. Lo stesso vale per i modelli di design. Inoltre, con i modelli di progettazione, il codice diventa più standard e, quando si utilizza il modello appropriato, è meno probabile che si commettano errori, poiché le insidie ​​comuni del modello sono state identificate ed eliminate molto tempo fa. Oltre a tutto il resto, la conoscenza dei modelli aiuta i programmatori a capirsi meglio. Puoi semplicemente pronunciare il nome di un pattern invece di cercare di fornire una lunga spiegazione ai tuoi colleghi programmatori. Riassumendo, i design pattern ti aiutano a:
  • non reinventare la ruota, ma utilizzare invece soluzioni standard;
  • standardizzare il codice;
  • standardizzare la terminologia;
Per concludere questa sezione, notiamo che l'intero corpo dei design pattern può essere suddiviso in tre grandi gruppi: Pattern e singleton - per tutti coloro che li incontrano per la prima volta - 2

Infine, il modello singleton

Singleton è un modello creazionale . Questo modello garantisce che vi sia una sola istanza di una classe e fornisce un punto di accesso globale per questo oggetto. Dalla descrizione, dovrebbe essere chiaro che questo modello dovrebbe essere applicato in due casi:
  1. quando il tuo programma richiede che non debba essere creato più di un oggetto di una particolare classe. Ad esempio, un gioco per computer potrebbe avere una classe Eroe e un solo oggetto Eroe che descrive l'unico eroe nel gioco.

  2. quando è necessario fornire un punto per l'accesso globale a un oggetto. In altre parole, è necessario rendere disponibile l'oggetto da qualsiasi punto del programma. Purtroppo, non è sufficiente creare semplicemente una variabile globale, poiché non è protetta da scrittura: chiunque può modificare il valore della variabile, quindi il punto di accesso globale dell'oggetto potrebbe andare perso. Queste proprietà di un Singleton sono necessarie, ad esempio, quando si dispone di un oggetto che funziona con un database ed è necessario accedere al database da diverse parti del programma. Un Singleton assicurerà che nessuno scriva codice che sostituisce l'istanza creata in precedenza.
Quindi un Singleton ha soddisfatto queste due esigenze: ci deve essere solo un oggetto di un certo tipo nel programma e ci deve essere un accesso globale ad esso. Nell'esempio al livello 15, il capitano ti chiede di implementare questo modello per il seguente compito:
  1. Trova un esempio di Singleton con inizializzazione pigra.

  2. Crea tre classi singleton - Sole, Luna, Terra - in file separati usando lo stesso principio.

  3. StrumentoPianetainterfaccia nelle classi Sole , Luna e Terra .

  4. Nel blocco statico della classe Solution chiama thereadKeyFromConsoleAndInitPlanetmetodo.

  5. Implementare ilreadKeyFromConsoleAndInitPlanetfunzionalità del metodo:

    • 5.1. Legge un parametro String dalla console

    • 5.2. Se il parametro è uguale a uno deiPianetacostanti dell'interfaccia, creare l'oggetto thePlanet adatto .

Dopo aver letto attentamente le condizioni del compito, possiamo vedere chiaramente perché qui è necessario un Singleton . Infatti, ci viene chiesto di creare un'istanza di ciascuna delle seguenti classi: Sun , Moon , Earth . Ha senso presumere che non dovremmo creare più di un Sole/Luna/Terra. Altrimenti, ci troviamo in una situazione assurda, a meno che tu non stia scrivendo la tua versione di Star Wars. Implementazione del modello Singleton in Java in tre passaggi In Java, il comportamento Singleton non può essere implementato utilizzando un normale costruttore, perché un costruttore restituisce sempre un nuovo oggetto. Pertanto, tutte le implementazioni di Singletonsi riduce a nascondere il costruttore, creando un metodo statico pubblico che controlla la durata dell'oggetto singleton e "distruggendo" tutti gli oggetti che appaiono di recente. Se si accede a Singleton , dovrebbe creare un nuovo oggetto (se non ne esiste già uno nel programma) o restituirne uno esistente. Per realizzare questo:
  1. Devi dare alla classe un campo statico privato che memorizza un singolo oggetto:

    
    public class LazyInitializedSingleton {
    	private static LazyInitializedSingleton instance; // #1
    }
    
  2. Rendi privato il costruttore (predefinito). Ciò significa che non è possibile accedervi al di fuori della classe e non sarà in grado di restituire nuovi oggetti:

    
    public class LazyInitializedSingleton {
    	private static LazyInitializedSingleton instance;
    private LazyInitializedSingleton(){} // #2
    } 
    
  3. Dichiara un metodo di creazione statico che verrà utilizzato per ottenere il singleton:

    
    public class LazyInitializedSingleton {
        private static LazyInitializedSingleton instance;
            private LazyInitializedSingleton() {}
            public static LazyInitializedSingleton getInstance() { // #3
            if (instance == null) { // If the object has not yet been created
                instance = new LazyInitializedSingleton(); // Create a new object
            }
            return instance; // Return the previously created object
        }
    }
    
L'esempio precedente è alquanto goffo, poiché nascondiamo semplicemente il costruttore e forniamo il nostro metodo invece di un costruttore standard. Poiché questo articolo mira a garantire che gli studenti di CodeGym entrino in contatto con questo modello (e con i modelli di progettazione in generale), le sfumature di implementazioni singleton più complesse non verranno descritte qui. Notiamo solo che, a seconda della complessità del programma, potrebbe essere necessario perfezionare ulteriormente questo schema. Ad esempio, in un ambiente multithread (vedere gli articoli sui thread), diversi thread possono accedere simultaneamente al metodo singleton e il codice descritto sopra smetterà di funzionare, poiché ogni thread separato potrebbe creare un'istanza della classe. Di conseguenza, esistono ancora diversi approcci alla creazione di singleton thread-safe appropriati. Ma questa è un'altra storia =)

E infine... Cos'è questa pigra inizializzazione di cui ha chiesto il capitano?

L'inizializzazione lazy è anche chiamata inizializzazione differita. Questo è un trucco di programmazione in cui un'operazione ad alta intensità di risorse (e la creazione di un oggetto è un'operazione ad alta intensità di risorse) viene eseguita su richiesta anziché in anticipo. Quindi cosa succede realmente nel nostro codice Singleton Java? In altre parole, il nostro oggetto viene creato al momento dell'accesso, non in anticipo. Non dovresti presumere che l'inizializzazione pigra sia in qualche modo rigidamente legata al modello Singleton . L'inizializzazione pigra viene utilizzata anche in altri modelli di progettazione creazionale, come Proxy e Factory Method, ma anche questa è un'altra storia =)
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION