Sommario:

Come eseguire il modello di progettazione Singleton in C++: 9 passaggi
Come eseguire il modello di progettazione Singleton in C++: 9 passaggi

Video: Come eseguire il modello di progettazione Singleton in C++: 9 passaggi

Video: Come eseguire il modello di progettazione Singleton in C++: 9 passaggi
Video: Композиция важнее наследования. Начало шаблонов проектирования iOS - raywenderlich.com 2024, Dicembre
Anonim
Come eseguire il modello di progettazione Singleton in C++
Come eseguire il modello di progettazione Singleton in C++

Introduzione:

Lo scopo di questa guida di istruzioni è insegnare all'utente come implementare il modello di progettazione singleton nel proprio programma C++. In tal modo, questo set di istruzioni spiegherà anche al lettore perché gli elementi di un singleton sono come sono e come viene elaborato il codice. Sapendo questo, ti aiuterà in futuro con il debug dei tuoi futuri singleton. Qual è il modello di design singleton? Il modello di progettazione singleton è un modello di progettazione in cui il programmatore crea una classe che può essere istanziata solo una volta, le funzioni pubbliche delle classi sono praticamente accessibili ovunque, a condizione che tu abbia #incluso il file di intestazione in altri file relativi al progetto.

Il modello di progettazione singleton è un modello di progettazione indispensabile per qualsiasi programmatore orientato agli oggetti, programmatori di software e programmatori di giochi. Il modello di progettazione singleton è anche uno dei modelli di progettazione di codifica più semplici in circolazione. Impararlo può aiutarti a imparare altri modelli di design più difficili in futuro. Può anche aiutarti a semplificare il codice del tuo programma in modi che non pensavi fossero possibili.

Mentre la difficoltà del modello di progettazione singleton è facile rispetto ad altri modelli di progettazione, questo set di istruzioni ha una difficoltà media. Ciò significa che per eseguire queste istruzioni, ti consigliamo di conoscere i requisiti di sintassi di base e avanzati di C++. Dovresti anche conoscere l'etichetta di codifica C++ corretta (ad es. Mantieni private le variabili di classe, una classe per file di intestazione, ecc.). Dovresti anche sapere come liberare memoria e come funzionano i costruttori e i distruttori in C++.

Questa guida didattica richiederà in media circa 10-15 minuti.

Requisiti materiali:

-Un computer (può essere PC o Mac) in grado di eseguire Visual Studios (qualsiasi versione)

-Un semplice programma, creato in Visual Studios, con cui puoi testare il tuo singleton

Nota: il modello di progettazione singleton può essere eseguito su qualsiasi altro C++ che supporta IDE o interfaccia di codifica, ma per questo set di istruzioni utilizzeremo Visual Studios Enterprise Edition.

Passaggio 1: crea la tua classe, con file di intestazione e file CPP

Crea la tua classe, con file di intestazione e file CPP
Crea la tua classe, con file di intestazione e file CPP
Crea la tua classe, con file di intestazione e file CPP
Crea la tua classe, con file di intestazione e file CPP

Per creare questi due file e la classe tutti in una volta, apri il tuo progetto / programma in Visual Studios, vai su Esplora soluzioni, fai clic con il pulsante destro del mouse e una casella dovrebbe apparire vicino al cursore del mouse, trova l'opzione "Aggiungi", passa il mouse sopra di esso, e un'altra casella dovrebbe apparire a destra. In questa casella, si desidera trovare l'opzione "Nuovo elemento..", fare clic su di essa e dovrebbe apparire una finestra, simile all'immagine 1.1 della foto qui sotto. In questa finestra si desidera selezionare "Classe C++" e quindi premere "Aggiungi". Si aprirà un'altra finestra che assomiglia all'immagine della foto 1.2. In questa finestra, digiti il nome della tua classe nel campo "Nome classe" e Visual Studios chiamerà automaticamente il file effettivo dopo il nome della classe. Ai fini di questa istruzione, chiameremo la nostra classe "EngineDebugSingleton", ma può essere qualsiasi nome basato su lettere. Ora puoi premere "OK" e procedere al passaggio 2.

Nota: Esplora soluzioni e dove sono conservati i file sul tuo computer sono separati. Lo spostamento o la creazione di elementi in Esplora soluzioni non sposterà né organizzerà i file all'interno di Esplora file del sistema operativo. Un modo sicuro per organizzare i file sul lato Esplora file sarebbe rimuovere, ma non eliminare i file specifici da Esplora soluzioni, spostare gli stessi file in Esplora file nella posizione desiderata e quindi tornare a Esplora soluzioni, fare clic con il pulsante destro del mouse, trova l'opzione "Aggiungi", quindi trova "Elemento esistente" e trova i file che hai spostato. Assicurati di spostare sia l'intestazione che il file cpp.

Passaggio 2: imposta il costruttore su Privato

Imposta il costruttore su Privato
Imposta il costruttore su Privato

Con il file CPP appena creato e il file di intestazione, se non si è aperto automaticamente quando lo hai creato, vai a Esplora soluzioni e fai clic e apri "EngineDebugSingleton.h". Verrai quindi accolto con un "EngineDebugSingleton()", il costruttore predefinito della classe e "~EngineDebugSingleton()" il distruttore della classe. Per questo passaggio, vorremo impostare il costruttore su privato, questo significa che questa funzione è disponibile solo per la classe e nient'altro. Con questo, non sarai in grado di creare una variabile o allocare la classe in memoria al di fuori della classe, solo nel file di intestazione delle classi e nelle altre funzioni delle classi. Avere il costruttore privato è fondamentale per il modello di progettazione e per il funzionamento dei singleton. Scopriremo nei passaggi futuri come viene istanziato e accessibile un singleton.

La classe ora dovrebbe apparire così dopo aver spostato il costruttore su privato (Guarda la foto associata)

Passaggio 3: imposta il distruttore su Privato

Imposta il Distruttore su Privato
Imposta il Distruttore su Privato

Come abbiamo fatto con il costruttore in

passaggio 2, per questo passaggio, ora imposteremo il distruttore su privato. Come con il costruttore, niente, eccetto la classe stessa, sarà in grado di cancellare qualsiasi variabile della classe dalla memoria.

La classe dovrebbe ora apparire così dopo aver completato questo passaggio. (Vedi foto associata)

Passaggio 4: creazione di una variabile puntatore statico nel Singleton

Creazione di una variabile puntatore statico nel Singleton
Creazione di una variabile puntatore statico nel Singleton

In questo passaggio, creeremo un

variabile puntatore statico di tipo “EngineDebugSingleton*”. Questa sarà la variabile che verrà utilizzata per allocare il nostro singleton in memoria e punterà ad esso per tutto il tempo in cui il nostro singleton sarà allocato in memoria.

Ecco come dovrebbe apparire il nostro file di intestazione dopo aver creato questa variabile

Passaggio 5: creazione di una funzione di istanza

Creazione di una funzione di istanza
Creazione di una funzione di istanza

Ora vogliamo fare un'istanza

funzione. La funzione dovrà essere una funzione statica e vorrà restituire un riferimento alla nostra classe ("EngineDebugSingleton&"). Abbiamo chiamato la nostra funzione Instance(). Nella funzione stessa, vorremo prima verificare se ptrInstance == nullptr (può essere abbreviato in !ptrInstance), se è nullptr, ciò significa che il singleton non è stato allocato e nell'ambito dell'istruzione if, desidera allocare facendo ptrInstance = new EngineDebugSingleton(). Qui è dove allochi effettivamente il singleton in memoria. Dopo essere usciti dall'ambito dell'istruzione if, restituiremo a cosa punta ptrInstance, che è indicato dalla sintassi "*ptrInstance". Utilizzeremo questa funzione pesantemente quando creeremo le nostre funzioni pubbliche statiche, in modo da poter verificare se il singleton è stato creato e allocato in memoria. In sostanza, questa funzione fa in modo che tu possa avere una sola allocazione della classe e non di più.

Ecco come dovrebbe apparire la nostra classe ora dopo aver creato la funzione Instance(). Come puoi vedere, tutto ciò che abbiamo fatto è rimasto nella sezione privata della classe, questo cambierà leggermente nei prossimi passaggi.

Passaggio 6: creazione di funzioni pubbliche statiche

Creazione di funzioni pubbliche statiche
Creazione di funzioni pubbliche statiche
Creazione di funzioni pubbliche statiche
Creazione di funzioni pubbliche statiche
Creazione di funzioni pubbliche statiche
Creazione di funzioni pubbliche statiche

Dopo aver creato la funzione da

passaggio 5, puoi iniziare a creare funzioni pubbliche statiche. Ogni funzione pubblica dovrebbe avere una funzione privata per accompagnarla, il nome di questa funzione non può essere lo stesso. Perché rendere la funzione Statica? Stiamo rendendo statiche le funzioni pubbliche in modo che sia possibile accedervi senza un oggetto reale. Quindi, invece di fare qualcosa come "EngineDebugSingleObj->SomeFunction()", facciamo "EngineDebugSingleton:: Some Function()". Ciò rende possibile l'accesso a un singleton praticamente ovunque nel codice, a condizione che tu abbia #incluso il file di intestazione nel file di progetto specifico con cui stai lavorando. Con questo, puoi anche creare il singleton attraverso una qualsiasi delle sue funzioni pubbliche.

Per i nostri scopi in questo passaggio abbiamo creato due funzioni void statiche pubbliche, "add()" e "subtract()". Nella sezione privata, abbiamo altre due funzioni, "PrivAdd()" e "PrivSubtract()". Abbiamo anche aggiunto una variabile int chiamata "NumberOfThings". La definizione di queste funzioni andrà nel file CPP delle nostre classi. Per fare in modo che la funzione entri facilmente nel file CPP, evidenzi, con il cursore, la funzione, che dovrebbe avere una linea verde sotto di essa, e premi "ALT+INVIO sinistro", ti darà l'opzione di creare la definizione nel file CPP associato alle classi. Guarda la foto 6.1 per vedere come dovrebbe essere il file di intestazione e dopo aver creato tutte le definizioni di funzione, il tuo CPP dovrebbe assomigliare alla foto 6.2 tranne per il fatto che le definizioni delle tue funzioni non avranno codice al loro interno.

Ora vorrai aggiungere lo stesso codice della foto 6.2 nelle definizioni delle funzioni. Come affermato in precedenza, le nostre funzioni pubbliche utilizzeranno la funzione Instance(), che restituirà ciò a cui punta ptrInstance. Questo ci permette di accedere alle funzioni private della nostra classe. Con qualsiasi funzione pubblica di singleton, dovresti chiamare solo quella funzione di istanza. L'unica eccezione è la nostra funzione Terminate.

Nota: le funzioni pubbliche e private esatte mostrate in questo passaggio non sono necessarie, puoi avere nomi di funzioni e operazioni diversi nella funzione privata, ma per qualsiasi tipo di funzione pubblica, dovresti avere una funzione privata per accompagnarla e la funzione pubblica dovrebbe sempre usare, nel nostro caso, la funzione Instance().

Passaggio 7: creazione della funzione di terminazione

Creazione della funzione di terminazione
Creazione della funzione di terminazione
Creazione della funzione di terminazione
Creazione della funzione di terminazione

Poiché possiamo solo deallocare il nostro singleton dalla memoria nella nostra classe, dobbiamo creare una funzione pubblica statica. Questa funzione chiamerà delete su ptrInstance, che chiama il distruttore di classe e quindi vorremo impostare ptrInstance su nullptr in modo che possa essere allocato di nuovo se il tuo programma non termina. Dovrai anche terminare i tuoi Singleton per ripulire qualsiasi memoria allocata che hai allocato nelle variabili private di qualsiasi Singleton.

Passaggio 8: impostazione di PtrInstance su Nullptr

Impostazione di PtrInstance su Nullptr
Impostazione di PtrInstance su Nullptr

Per completare il tuo singleton, devi andare al file EngineDebugSingleton. CPP e nella parte superiore del file CPP, nel nostro caso, digita "EngineDebugSingleton* EngineDebugSingleton::ptrInstance = nullptr".

In questo modo inizialmente si imposterà ptrInstance su nullptr, quindi quando si esegue per la prima volta la funzione di istanza, la nostra classe potrà essere allocata in memoria. Senza di esso, molto probabilmente otterrai un errore perché proverai ad accedere alla memoria a cui non è stato assegnato nulla.

Passaggio 9: test e conclusione

Test e Conclusione
Test e Conclusione

Ora vorremo testare che il nostro singleton per assicurarci che funzioni, questo comporterà che chiamiamo le funzioni pubbliche come descritto nel passaggio 6 e ti consigliamo di impostare punti di interruzione per scorrere il codice e vedere che il singleton funziona come dovrebbe essere. Il nostro punto di partenza sarà nel main.cpp del nostro progetto e il nostro main.cpp ora ha l'aspetto dell'immagine qui sotto.

Congratulazioni! Hai appena completato la tua prima implementazione del Singleton Design Pattern. Con questo modello di progettazione, ora puoi semplificare il tuo codice in vari modi. Ad esempio, ora puoi creare sistemi di gestione che operano durante il tempo di esecuzione del tuo programma, a cui è possibile accedere tramite funzioni statiche ovunque tu abbia incluso la classe.

Il tuo file di intestazione finale dovrebbe assomigliare alla foto 7.1. Il file CPP associato al tuo singleton dovrebbe essere simile alla foto 6.2 con l'aggiunta, nella parte superiore del file, del codice mostrato nel passaggio 8. Questa istruzione ti ha fornito una struttura semplice del modello di progettazione Singleton.

Consigli per la risoluzione dei problemi:

Ottenere errori relativi alla memoria?

Assicurati di fare riferimento al passaggio 7 e al passaggio 8 per assicurarti di impostare ptrInstance su nullptr.

Ciclo infinito che si verifica?

Assicurati che per le funzioni pubbliche, nelle loro definizioni, chiami la funzione privata, non la stessa funzione pubblica.

Oggetti allocati all'interno del singleton che causano perdite di memoria?

Assicurati di chiamare la funzione di terminazione del tuo singleton quando appropriato all'interno del codice del tuo programma e, nel distruttore del tuo singleton, assicurati di deallocare tutti gli oggetti che sono stati assegnati alla memoria nell'ambito del codice singleton.