Menu
Coddy logo textTech

Pattern Singleton

Fa parte della sezione Programmazione orientata agli oggetti del percorso Java di Coddy. Lezione 65 di 87.

Il Singleton Pattern è un pattern di progettazione creazionale che garantisce che una classe abbia una sola istanza in tutta l'applicazione, fornendo al contempo un punto di accesso globale a tale istanza. È utile per le risorse che dovrebbero essere condivise, come i gestori della configurazione, i pool di connessioni o i servizi di logging.

Il pattern funziona rendendo privato il costruttore, impedendo l’istanziazione diretta. Invece, un metodo statico controlla l’accesso all’unica istanza:

public class DatabaseConnection {
    private static DatabaseConnection instance;
    
    // Il costruttore privato impedisce l'istanziazione diretta
    private DatabaseConnection() {
        System.out.println("Connection created");
    }
    
    // Punto di accesso globale
    public static DatabaseConnection getInstance() {
        if (instance == null) {
            instance = new DatabaseConnection();
        }
        return instance;
    }
    
    public void query(String sql) {
        System.out.println("Executing: " + sql);
    }
}

Ogni chiamata a getInstance() restituisce lo stesso oggetto. L’istanza viene creata solo quando viene richiesta per la prima volta. Questo si chiama inizializzazione lazy:

DatabaseConnection db1 = DatabaseConnection.getInstance();
DatabaseConnection db2 = DatabaseConnection.getInstance();

System.out.println(db1 == db2);  // true - stessa istanza

I componenti chiave di un Singleton sono: un campo private static che contiene l’istanza, un costruttore private e un metodo public static che restituisce l’istanza. Questa combinazione garantisce che, indipendentemente da quante volte richiedi l’oggetto, ottieni sempre lo stesso.

challenge icon

Sfida

Facile

Creiamo un gestore della configurazione per un'applicazione usando il Pattern Singleton! Il gestore della configurazione garantirà che tutte le parti della tua applicazione condividano le stesse impostazioni, indipendentemente da quante volte ne richiedano l'accesso.

Organizzerai il codice in due file:

  • AppConfig.java: crea una classe Singleton che gestisce le impostazioni di configurazione dell'applicazione. La tua classe AppConfig dovrebbe avere:

    Un campo statico privato che contiene l'unica istanza.

    Un campo String privato chiamato appName e un campo int privato chiamato maxUsers.

    Un costruttore privato che inizializza appName a "MyApplication" e maxUsers a 100, quindi stampa AppConfig initialized.

    Un metodo getInstance() statico pubblico che crea l'istanza solo se non esiste ancora (inizializzazione lazy), quindi la restituisce.

    Un metodo setAppName(String name) che aggiorna il nome dell'app.

    Un metodo setMaxUsers(int max) che aggiorna il numero massimo di utenti.

    Un metodo displaySettings() che stampa App: [appName], Max Users: [maxUsers].

  • Main.java: dimostra che il tuo Singleton funziona correttamente! Riceverai due input: un nuovo nome per l'app (String) e un nuovo numero massimo di utenti (intero).

    Per prima cosa, ottieni un'istanza di AppConfig e assegnala a una variabile chiamata config1. Chiama displaySettings() per mostrare i valori predefiniti.

    Poi aggiorna le impostazioni usando i valori di input, chiamando setAppName e setMaxUsers su config1.

    Ottieni un'altra istanza e assegnala a config2. Chiama displaySettings() su config2 per dimostrare che riflette le modifiche apportate tramite config1.

    Infine, stampa se entrambi i riferimenti puntano allo stesso oggetto: Same instance: [true/false], confrontando config1 == config2.

Riceverai due input in quest'ordine: il nuovo nome dell'app (String) e il nuovo numero massimo di utenti (intero).

Questa sfida dimostra il vantaggio fondamentale del Pattern Singleton: indipendentemente da quante volte richiedi la configurazione, ottieni sempre la stessa istanza con lo stesso stato condiviso!

Provalo tu

import java.util.Scanner;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        // Leggi gli input
        String newAppName = scanner.nextLine();
        int newMaxUsers = scanner.nextInt();
        
        // TODO: Ottieni la prima istanza di AppConfig e memorizzala in config1
        
        // TODO: Chiama displaySettings() su config1 per mostrare i valori predefiniti
        
        // TODO: Aggiorna le impostazioni usando setAppName e setMaxUsers su config1
        
        // TODO: Ottieni un'altra istanza e memorizzala in config2
        
        // TODO: Chiama displaySettings() su config2 per dimostrare che le modifiche sono condivise
        
        // TODO: Stampa se entrambi i riferimenti puntano allo stesso oggetto:
        // "Same instance: [true/false]" usando config1 == config2
    }
}
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Java online