LA CAMPANA

C’è chi ha letto questa notizia prima di te.
Iscriviti per ricevere nuovi articoli.
E-mail
Nome
Cognome
Come vuoi leggere La Campana?
Niente spam

Solitarioè un modello di progettazione generativa che garantisce che una classe abbia una sola istanza e fornisce ad essa un punto di accesso globale.

Problema

Un solitario risolve due problemi contemporaneamente, violando principio di responsabilità unica classe.

    Garantisce l'esistenza di una singola istanza di una classe. Questo è spesso utile per accedere ad alcune risorse condivise, come un database.

    Immagina di aver creato un oggetto e dopo un po' di provare a crearne un altro. In questo caso, vorrei ottenere il vecchio oggetto invece di crearne uno nuovo.

    Questo comportamento non può essere ottenuto utilizzando un costruttore regolare, poiché il costruttore della classe Sempre restituisce un nuovo oggetto.


I clienti potrebbero non rendersi conto che stanno lavorando con lo stesso oggetto.

    Fornisce un punto di accesso globale. Questa non è solo una variabile globale attraverso la quale è possibile accedere a un oggetto specifico. Le variabili globali non sono protette da scrittura, quindi qualsiasi codice può modificare i loro valori a tua insaputa.

    Ma c'è un'altra sfumatura. Sarebbe bello archiviare il codice che risolve il problema n. 1 in un unico posto e anche avere un'interfaccia semplice e accessibile.

È interessante notare che ai nostri giorni il modello è diventato così noto che le persone ora chiamano "single" anche quelle classi che risolvono solo uno dei problemi sopra elencati.

Soluzione

Tutte le implementazioni singleton si riducono a nascondere il costruttore predefinito e creare un metodo statico pubblico che controllerà il ciclo di vita dell'oggetto singleton.

Se hai accesso alla classe singleton, avrai accesso a questo metodo statico. Non importa dove lo chiami nel codice, restituirà sempre lo stesso oggetto.

Analogia dalla vita

Il governo di uno stato è un buon esempio di solitario. Uno stato può avere un solo governo ufficiale. Indipendentemente da chi siede esattamente nel governo, ha un punto di accesso globale “Governo del Paese N”.

Struttura



    Solitario definisce un metodo statico getInstance che restituisce una singola istanza della sua classe.

    Il costruttore singleton deve essere nascosto ai client. Chiamare il metodo getInstance dovrebbe essere l'unico modo per ottenere un oggetto di questa classe.

Pseudocodice

In questo esempio il ruolo Single riproduce la classe di connessione al database.

Questa classe non ha un costruttore pubblico, quindi l'unico modo per ottenere il suo oggetto è chiamare il metodo getInstance. Questo metodo salverà il primo oggetto creato e lo restituirà a tutte le chiamate successive.

// La classe singleton definisce un metodo statico `getInstance` che // consente ai client di riutilizzare la stessa // connessione al database in tutto il programma. class Database è // Il campo per la memorizzazione di un singolo oggetto deve essere dichiarato // statico.

istanza del campo statico privato: Database // Un costruttore singleton dovrebbe sempre rimanere privato in modo che // i client non possano creare // istanze di questa classe da soli tramite l'operatore "new".

il costruttore privato Database() è // Il codice di inizializzazione per la connessione al // server del database può risiedere qui.

Il singleton nasconde ai client tutti i metodi per creare un nuovo oggetto, ad eccezione di un metodo speciale. Questo metodo crea un oggetto o restituisce un oggetto esistente se ne è già stato creato uno.

Quando vuoi avere maggiore controllo sulle variabili globali.

A differenza delle variabili globali, i Singleton assicurano che nessun altro codice sostituisca l'istanza istanziata della classe, quindi sei sempre sicuro che esista un solo oggetto singleton.

Tuttavia, in qualsiasi momento è possibile estendere questa limitazione per consentire un numero qualsiasi di oggetti singleton modificando il codice in un unico posto (il metodo getInstance).

Fasi di implementazione

    Aggiungi un campo statico privato alla classe che conterrà un singolo oggetto.

    Dichiarare un metodo di creazione statico che verrà utilizzato per ottenere il singleton.

22.10.2015
23:12

Lo scopo del modello Singleton (o Singleton) è fornire l'accesso a qualche oggetto univoco da qualsiasi punto dell'applicazione. Unicità significa che un tale oggetto esiste in memoria in una singola copia e non è possibile creare altre copie.

Senza la condizione di unicità, Singleton è una variabile globale ordinaria, tenendo conto dei pro e dei contro risultanti (che sono la maggioranza). Quindi, prima di utilizzare questo modello, assicurati che si adatti perfettamente. L'oggetto che dovrebbe essere implementato come Singleton deve essere veramente unico a livello di sistema.

Esempio di implementazione del modello Singleton in C++

Tecnicamente, implementare un oggetto Singleton e utilizzarlo in un'applicazione è abbastanza semplice (il che è accattivante):

#includere class MySingleton ( public: // Funzione membro per accedere a una singola istanza static MySingleton* getInstance() ( istanza statica MySingleton; return ) // Riempila con funzionalità utili, come qualsiasi altra classe void test() ( std::cout<< "Singleton test" << std::endl; } private: // Объявляем конструктор закрытым, чтобы нельзя было // создавать экземпляры класса извне MySingleton() { } }; int main() { // Используем Синглтон MySingleton::getInstance()->test(); // Ma questo non funzionerà, poiché il costruttore è privato // MySingleton singleton;

restituire 0; )

Se lo si desidera, un oggetto Singleton può essere adattato a un ambiente di esecuzione multi-thread utilizzando i mutex.

Pubblicità

Pensa sempre prima di creare Singleton

Diamo un'occhiata a un esempio. Potrebbe sembrare una buona idea creare una classe per gestire le impostazioni dell'applicazione come Singleton. Quindi tutti i componenti dell'applicazione saranno in grado di vedere le opzioni necessarie e utilizzarle facilmente. Da un lato, l’idea sembra piuttosto buona. La configurazione di un'applicazione può infatti essere rappresentata da un'entità univoca. E l'accesso gratuito a Singleton semplificherà l'uso della configurazione.

Tuttavia, in questo caso si pone un problema serio. Tutti i componenti iniziano a dipendere da Singleton. Se devi trasferire solo una delle classi in un'altra applicazione, dovrai trascinare con sé Singleton, che può essere progettato per gestire i parametri di decine di altre classi. È meglio dedicare un po' più di tempo alla progettazione, ma assicurarsi che i parametri siano chiaramente passati alle classi attraverso i loro costruttori, piuttosto che attraverso un Singleton poco appariscente.

Inoltre, il modello Singleton complica l'uso del polimorfismo e di altri vantaggi dell'OOP, che potrebbero essere necessari quando il refactoring minimo non è più sufficiente.

Sebbene esistano applicazioni abbastanza innocue di Singleton. Ad esempio, quando si implementa un altro modello: Abstract Factory.

Inoltre, l'uso di Singleton è giustificato per rappresentare risorse informatiche fisicamente uniche. Sarebbe ad esempio opportuno implementare un sistema di monitoraggio della connessione/disconnessione dei dispositivi USB sotto forma di Singleton.

Un singleton è un pattern che appartiene al gruppo dei pattern generatori (shiblon).

Scopo

Garantisce che una classe abbia una sola istanza (ancor più precisamente possiamo dire che "può esserci una sola istanza di una classe di un determinato tipo") e fornisce un punto di accesso globale ad esso.

Soprannome

Il nome inglese Singleton (singleton) è spesso tradotto in testi in lingua russa e il modello Singleton si chiama “Singleton”. Utilizzeremo il nome russo perché ha molto successo.

Motivazione

Per alcune classi è importante che esista una sola istanza.
Per esempio:

  1. Sebbene in un sistema possano essere presenti molte stampanti, è possibile un solo spooler.
  2. Dovrebbe esserci un solo file system e un unico gestore di finestre.
  3. Un filtro digitale può contenere solo un convertitore analogico-digitale (ADC). Il sistema contabile serve una sola azienda.

Come garantirlo la classe ha una singola istanza e che questa istanza è facilmente accessibile?
Una variabile globale dà accesso a un oggetto, ma non impedisce la creazione di un'istanza della classe in diversi casi.
Una soluzione migliore si ottiene se la classe stessa:

  1. controlla che abbia solo un'istanza
  2. può impedire la creazione di istanze aggiuntive intercettando le richieste di creazione di nuovi oggetti
  3. ed è anche in grado di fornire l'accesso alla sua copia.

Applicazioni conosciute

Viene utilizzato in molti sistemi che simulano oggetti reali.

Modelli correlati

Molti modelli possono essere implementati utilizzando il modello singleton.
Vedi la descrizione.

Oggi voglio sistemare la cosa modello di progettazione singleton, che viene spesso utilizzato nella programmazione orientata agli oggetti.

Modello di disegno singolo O Modello Singletonè necessario in modo da non avere molti oggetti dello stesso tipo, ma ne viene sempre utilizzato solo uno. Un esempio è una classe per lavorare con un database.

DB Classe(
protetto $db;

Funzione pubblica __construct() (
$questo->
}

Funzione pubblica get() ()
insieme di funzioni pubbliche()
funzione pubblica del() ()
}

$db1 = nuovo DB();
$db2 = nuovo DB();

Lo abbiamo già fatto 2 oggetto $db1 E $db2, e poi qualcuno, non sapendo che un tale oggetto esiste già, ne creerà un terzo, ecc. Ciò ha un effetto molto negativo sulle prestazioni e sulla leggibilità del codice e nel nostro caso potrebbe bloccarsi, perché L'hosting ha un numero limitato di connessioni al database.

È stato inventato per risolvere questo problema modello singleton.

DB Classe(
protetto $db;
$istanza privata statica = null;

Funzione privata __construct() (
$this->db = new Mysqli($host, $utente, $pass, $database);
}

Funzione privata __clone() ()

Funzione statica getInstance() (
if(self::$istanza == null) (
self::$istanza = new self();
}
return self::$istanza;
}
}

$db = nuovo DB(); // errore

$db = DB::getInstance();
$db2 = DB::getInstance();
$db3 = DB::getInstance();

Per rendere impossibile la creazione di un oggetto nel solito modo, creiamo il nostro costruttore privato, ma non dimenticare anche che gli oggetti possono clone e chiudi anche il metodo __clone. Successivamente creiamo una proprietà statica $istanza, che per impostazione predefinita è nullo. Ora creiamo un metodo statico getIstanza() che controlla se la nostra proprietà statica è uguale a nullo? Se sì, creiamo un'istanza del nostro oggetto e la restituiamo, altrimenti la restituiamo semplicemente. In questo modo avremo sempre la stessa istanza, non importa quante volte le creeremo. Utilizzarlo è molto semplice: assegna ad una variabile il valore che viene restituito dal metodo statico getIstanza(), classe D.B., e poi lavoriamo come con un oggetto normale.

Classe Singleton ( private static $PrS="init private"; public static $PuS="init public"; funzione statica pubblica PrS($A=false) ( if($A!==false) self::$PrS=$ A; altrimenti restituisce self::$PrS; ) funzione statica pubblica PuS($A=false) ( if($A!==false) self::$PuS=$A; altrimenti restituisce self::$PuS; ) ) echo Singleton::PrS(); echo "\n"; echo Singleton::PuS(); // stampa init private // init public echo "\n -- \n"; $D = nuovo Singleton(); echo $D->PrS(); // stamperà anche l'eco privato di init "\n"; // init public echo $D->PuS(); echo "\n -- \nIMPOSTALI tutti!"; // E qui Singleton::PrS("cambiato privato"); // cambia le variabili della classe Singleton::PuS("changed public"); // utilizzando un collegamento statico echo "\n"; // e proviamo a controllarli dalla classe "creata" (anche se questo è solo un collegamento di copia) echo $D->PrS(); // ovviamente verrà restituito: changed private echo "\n"; echo $D->PuS(); // cambiato pubblico

copia questo semplice esempio, eseguilo e capirai che una classe statica, insieme alle sue variabili statiche, non viene duplicata dall'operatore new. Anche se fai dieci riprese, è sempre lo stesso: le variabili statiche rimarranno.

La parola statica per una funzione significa che nella tabella globale, durante la compilazione, le è già assegnato un indirizzo - allocato in modo rigido. Lo stesso vale per le variabili statiche: anche il loro indirizzo è statico. E le variabili NON statiche (classi) non esistono nello spazio degli indirizzi finché non vengono definite (con l'operatore new). Non c'è nessun posto a cui rivolgersi. Per quelli statici, l'indirizzo esiste già - e puoi sempre accedervi (la variabile) - someStaticClass::value

Se desideri utilizzare una classe statica per lavorare con un database, crea una variabile statica privata DB_handler al suo interno. È necessario lavorare con più connessioni (diversi database): crearne di più se necessario. Puoi persino creare qualcosa come un array statico. Perché no? Se hai bisogno di essere troppo creativo, riscrivi la lezione. Quelli. le copie delle classi statiche non differiscono affatto (se create dall'operatore new) finché non appare in esse almeno una variabile NON statica. È vero, anche dopo differiranno solo per questa variabile NON statica. È vero, allo stesso tempo, sarà possibile controllare questa variabile solo dalla classe prodotta.

Funzione statica pubblica getInstance() ( if (is_null(self::$instance)) ( self::$instance = new Singleton; ) return self::$instance; )

Questo pezzo di codice restituisce una copia del collegamento all'indirizzo della classe statica Singleton. È come scrivere Singleton::(e c'è qualcosa lì)

Ecco di cosa si trattava la domanda: "PERCHÉ?" La risposta è semplice: sì, NON C'È BISOGNO :)

Probabilmente ci sono attività in cui è necessario creare un'istanza della classe Singleton, " ...ma se non ci fossero richieste (beh, qualcosa non serviva), allora non si avvierà nulla e tutto sarà tranquillo e calmo... Ma sembra che esisterà una classe statica anche quando potrebbe non essere necessaria. .. e wow, quanto terribilmente divorerà la memoria...“In generale, per qualche motivo non riesco a trovare subito un compito che utilizzi la CREAZIONE di classi invece di classi statiche.

E ad esempio, non vedo nemmeno la differenza tra un complesso Singleton bloat e un semplice Singleton::doAction(). In generale, anche le classi statiche (con variabili statiche) sono estremamente convenienti perché forniscono, per così dire, variabili “globali” per qualsiasi ambito. E il gestore del database ne è un ottimo esempio.

LA CAMPANA

C’è chi ha letto questa notizia prima di te.
Iscriviti per ricevere nuovi articoli.
E-mail
Nome
Cognome
Come vuoi leggere La Campana?
Niente spam