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 istanzaI 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.
Sfida
FacileCreiamo 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 classeAppConfigdovrebbe avere:Un campo statico privato che contiene l'unica istanza.
Un campo String privato chiamato
appNamee un campo int privato chiamatomaxUsers.Un costruttore privato che inizializza
appNamea"MyApplication"emaxUsersa100, quindi stampaAppConfig 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 stampaApp: [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
AppConfige assegnala a una variabile chiamataconfig1. ChiamadisplaySettings()per mostrare i valori predefiniti.Poi aggiorna le impostazioni usando i valori di input, chiamando
setAppNameesetMaxUserssuconfig1.Ottieni un'altra istanza e assegnala a
config2. ChiamadisplaySettings()suconfig2per dimostrare che riflette le modifiche apportate tramiteconfig1.Infine, stampa se entrambi i riferimenti puntano allo stesso oggetto:
Same instance: [true/false], confrontandoconfig1 == 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
}
}
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
1Fondamenti della programmazione a oggetti
File esterniIntroduzione alla programmazione a oggettiClassi e oggettiLa parola chiave thisMetodiCampi (attributi)Metodo costruttoreSovraccarico dei costruttoriRipasso - Calcolatrice semplice4Ereditarietà
Ereditarietà di base (extends)La parola chiave superSovrascrittura dei metodi (@Override)Concatenamento dei costruttoriLa classe ObjectEreditarietà singola e multilivelloPerché non esiste l'ereditarietà multipla delle classiRiepilogo: gerarchia dei dipendenti7Metodi speciali e classe Object
Metodo toString()equals() e hashCode()Metodo clone()compareTo() e ComparableInterfaccia ComparatorRiepilogo - Ordinamento personalizzato2Modificatori di accesso e incapsulamento
Panoramica dei livelli di accessoMetodi getter e setterNascondimento delle informazioniLa parola chiave finalRiepilogo - Gestore di conti bancari5Polimorfismo
Nozioni di base sull'overloading dei metodiOverride dei metodi (a runtime)Upcasting e downcastingL'operatore instanceofClassi e metodi astrattiRiepilogo - Calcolatore di forme8Concetti avanzati di OOP
Composizione vs ereditarietàAggregazione vs composizioneClassi interne, annidate e anonimeEnum e metodi degli EnumRecord (Java 16+)Classi sealed (Java 17+)11Modelli di progettazione Parte 1
Introduzione ai modelli di progettazionePattern SingletonPattern FactoryPattern BuilderPattern ObserverPattern Strategy3Proprietà di classe e membri statici
Variabili di istanza e staticheMetodi staticiBlocchi staticiCostanti (static final)Riepilogo - Contatore e utility6Interfacce e classi astratte
Introduzione alle interfacceImplementazione delle interfacceImplementazione di più interfacceMetodi default e static nelle interfacceClassi astratte e interfacce a confrontoInterfacce funzionaliRiepilogo: sistema di pagamento9Tipi generici
Introduzione ai tipi genericiClassi genericheMetodi genericiParametri di tipo con limitiCaratteri jolly (?, extends, super)Riepilogo - Contenitore generico12Modelli di progettazione – Parte 2
Pattern CommandPattern AdapterPattern DecoratorPattern Template MethodPattern StatePattern CompositePattern IteratorEsercitati da solo: Compilatore Java online