Spisu treści:

Jak wykonać wzorzec projektowy Singleton w C++: 9 kroków
Jak wykonać wzorzec projektowy Singleton w C++: 9 kroków

Wideo: Jak wykonać wzorzec projektowy Singleton w C++: 9 kroków

Wideo: Jak wykonać wzorzec projektowy Singleton w C++: 9 kroków
Wideo: 8. Programowanie obiektowe - Klasy, konstruktory, destruktor, static 2024, Czerwiec
Anonim
Jak wykonać wzorzec projektowy Singleton w C++
Jak wykonać wzorzec projektowy Singleton w C++

Wstęp:

Celem tego przewodnika jest nauczenie użytkownika, jak zaimplementować wzorzec projektowy singletona w swoim programie C++. W ten sposób ten zestaw instrukcji wyjaśni również czytelnikowi, dlaczego elementy singletona są takie, jakie są i jak przetwarzany jest kod. Wiedząc o tym, pomożesz w przyszłości w debugowaniu twoich przyszłych singletonów. Jaki jest wzorzec projektowy singletona? Wzorzec projektowy singleton to wzorzec projektowy, w którym programista tworzy klasę, która może być skonkretyzowana tylko raz, publiczne funkcje klas są zasadniczo dostępne z dowolnego miejsca, pod warunkiem, że #zawarłeś plik nagłówkowy w innych plikach związanych z projektem.

Wzorzec projektowy singleton jest obowiązkowym wzorcem projektowym dla każdego programisty obiektowego, programisty oprogramowania i programisty gier. Wzorzec projektowy singleton jest również jednym z najłatwiejszych wzorców projektowych do kodowania. Nauka tego może pomóc w nauce innych, trudniejszych wzorców projektowych w przyszłości. Może również pomóc w usprawnieniu kodu programu w sposób, o którym nie myślałeś, że jest to możliwe.

Chociaż trudność wzorca projektowego singleton jest łatwa w porównaniu z innymi wzorcami projektowymi, ten zestaw instrukcji ma średnią trudność. Oznacza to, że aby wykonać te instrukcje, zalecamy znajomość podstawowych i zaawansowanych wymagań dotyczących składni języka C++. Powinieneś także znać właściwą etykietę kodowania C++ (tj. Zachowaj prywatność zmiennych klas, po jednej klasie na plik nagłówkowy itp.). Powinieneś także wiedzieć, jak zwolnić pamięć i jak działają konstruktory i destruktory w C++.

Ten przewodnik instruktażowy zajmie średnio około 10-15 minut.

Wymagania materiałowe:

- Komputer (może to być komputer PC lub Mac) obsługujący program Visual Studios (dowolna wersja)

-Prosty program stworzony w Visual Studios, za pomocą którego możesz przetestować swojego singletona

Uwaga: Wzorzec projektu singleton można wykonać w dowolnym innym C++ obsługującym IDE lub interfejs kodowania, ale dla tego zestawu instrukcji będziemy używać Visual Studios Enterprise Edition.

Krok 1: Utwórz swoją klasę za pomocą pliku nagłówka i pliku CPP

Stwórz swoją klasę za pomocą pliku nagłówka i pliku CPP
Stwórz swoją klasę za pomocą pliku nagłówka i pliku CPP
Stwórz swoją klasę za pomocą pliku nagłówka i pliku CPP
Stwórz swoją klasę za pomocą pliku nagłówka i pliku CPP

Aby utworzyć te dwa pliki i całą klasę jednocześnie, otwórz projekt / program w Visual Studios, przejdź do eksploratora rozwiązań, kliknij prawym przyciskiem myszy, a obok kursora myszy powinno pojawić się pole, znajdź opcję „Dodaj”, najedź na nad nim, a po prawej stronie powinno pojawić się kolejne pole. W tym polu chcesz znaleźć opcję „Nowa pozycja..”, kliknij ją, a powinno pojawić się okno przypominające zdjęcie 1.1 poniżej. W tym oknie chcesz wybrać „Klasę C++”, a następnie nacisnąć „Dodaj”. Spowoduje to otwarcie kolejnego okna, które przypomina zdjęcie 1.2. W tym oknie wpisz nazwę swojej klasy w polu „Nazwa klasy”, a Visual Studios automatycznie nada rzeczywistemu plikowi nazwę po nazwie klasy. Na potrzeby tej instrukcji nazwiemy naszą klasę „EngineDebugSingleton”, ale może to być dowolna nazwa oparta na literach. Możesz teraz nacisnąć „OK” i przejść do kroku 2.

Uwaga: Eksplorator rozwiązań i miejsce przechowywania plików na komputerze są oddzielne. Przenoszenie lub tworzenie czegokolwiek w eksploratorze rozwiązań nie spowoduje przeniesienia ani uporządkowania plików w eksploratorze plików systemu operacyjnego. Bezpiecznym sposobem na uporządkowanie plików po stronie eksploratora plików byłoby usunięcie, ale nie usunięcie określonych plików z eksploratora rozwiązań, przeniesienie tych samych plików w eksploratorze plików do żądanej lokalizacji, a następnie powrót do eksploratora rozwiązań, kliknięcie prawym przyciskiem myszy, znajdź opcję „Dodaj”, a następnie znajdź „Istniejący element” i znajdź przeniesione pliki. Upewnij się, że przenosisz zarówno plik nagłówka, jak i plik cpp.

Krok 2: Ustaw konstruktora na prywatny

Ustaw konstruktora na prywatny
Ustaw konstruktora na prywatny

Z nowo utworzonym plikiem CPP i plikiem nagłówkowym, jeśli nie otworzył się automatycznie podczas jego tworzenia, przejdź do eksploratora rozwiązań i kliknij i otwórz „EngineDebugSingleton.h”. Zostaniesz powitany „EngineDebugSingleton()”, domyślnym konstruktorem klasy i „~EngineDebugSingleton()” destruktorem klasy. W tym kroku będziemy chcieli ustawić konstruktor na prywatny, co oznacza, że ta funkcja jest dostępna tylko dla klasy i nic więcej. Dzięki temu nie będziesz w stanie utworzyć zmiennej ani przydzielić klasy do pamięci poza klasą, tylko w pliku nagłówkowym klas i innych funkcjach klas. Posiadanie prywatnego konstruktora jest kluczem do wzorca projektowego i sposobu działania singletonów. W kolejnych krokach dowiemy się, w jaki sposób tworzy się i uzyskuje dostęp do singletona.

Klasa powinna teraz wyglądać tak po przeniesieniu konstruktora na prywatny (patrz na powiązane zdjęcie)

Krok 3: Ustaw destruktor na prywatny

Ustaw destruktor na prywatny
Ustaw destruktor na prywatny

Tak jak zrobiliśmy z konstruktorem w

krok 2, w tym kroku ustawimy teraz destruktor na prywatny. Podobnie jak w przypadku konstruktora, nic poza samą klasą nie będzie w stanie usunąć z pamięci żadnych zmiennych klasy.

Klasa powinna teraz wyglądać tak po wykonaniu tego kroku. (Patrz powiązane zdjęcie)

Krok 4: Tworzenie zmiennej wskaźnika statycznego w Singletonie

Tworzenie zmiennej wskaźnika statycznego w Singletonie
Tworzenie zmiennej wskaźnika statycznego w Singletonie

W tym kroku stworzymy

statyczna zmienna wskaźnikowa typu „EngineDebugSingleton*”. Będzie to zmienna, która posłuży do przydzielenia naszego singletona do pamięci i będzie na niego wskazywać przez cały czas, kiedy nasz singleton jest przyporządkowany do pamięci.

Tak powinien wyglądać nasz plik nagłówkowy po utworzeniu tej zmiennej

Krok 5: Tworzenie funkcji instancji

Tworzenie funkcji instancji
Tworzenie funkcji instancji

Teraz chcemy zrobić instancję

funkcjonować. Funkcja będzie musiała być funkcją statyczną i będzie zwracać referencję do naszej klasy („EngineDebugSingleton&”). Naszą funkcję nazwaliśmy Instance(). W samej funkcji będziemy chcieli najpierw przetestować, czy ptrInstance == nullptr (można skrócić do !ptrInstance), jeśli jest to nullptr, oznacza to, że singleton nie został zaalokowany i w zakresie instrukcji if będziemy chcesz przydzielić, wykonując ptrInstance = new EngineDebugSingleton(). W tym miejscu faktycznie przydzielasz singletona do pamięci. Po wyjściu z zakresu instrukcji if zwrócimy to, na co wskazuje ptrInstance, co oznacza składnia „*ptrInstance”. Będziemy intensywnie używać tej funkcji podczas tworzenia naszych statycznych funkcji publicznych, więc możemy sprawdzić, czy singleton został utworzony i przydzielony do pamięci. Zasadniczo ta funkcja sprawia, że możesz mieć tylko jedną alokację klasy i nie więcej.

Tak powinna wyglądać teraz nasza klasa po utworzeniu funkcji Instance(). Jak widać, wszystko, co zrobiliśmy, pozostało w prywatnej sekcji zajęć, co nieco się zmieni w kilku następnych krokach.

Krok 6: Tworzenie statycznych funkcji publicznych

Tworzenie statycznych funkcji publicznych
Tworzenie statycznych funkcji publicznych
Tworzenie statycznych funkcji publicznych
Tworzenie statycznych funkcji publicznych
Tworzenie statycznych funkcji publicznych
Tworzenie statycznych funkcji publicznych

Po wykonaniu funkcji z

krok 5, możesz zacząć tworzyć statyczne funkcje publiczne. Każda funkcja publiczna powinna mieć funkcję prywatną, aby towarzyszyć jej, nazwa tej funkcji nie może być taka sama. Dlaczego funkcja jest statyczna? Sprawiamy, że funkcje publiczne stają się statyczne, aby można było uzyskać do nich dostęp bez rzeczywistego obiektu. Więc zamiast robić coś takiego jak „EngineDebugSingleObj->SomeFunction()”, robimy „EngineDebugSingleton:: Some Function()”. Umożliwia to dostęp do singletona praktycznie w dowolnym miejscu w kodzie, pod warunkiem, że #zawarłeś plik nagłówkowy w konkretnym pliku projektu, z którym pracujesz. Dzięki temu możesz również stworzyć singletona poprzez dowolną z jego funkcji publicznych.

Dla naszych celów w tym kroku stworzyliśmy dwie publiczne statyczne funkcje void, „add()” i „subtract()”. W sekcji prywatnej mamy jeszcze dwie funkcje, „PrivAdd()” i „PrivSubtract()”. Dodaliśmy również zmienną int o nazwie „NumberOfThings”. Definicja tych funkcji zostanie umieszczona w pliku CPP naszych klas. Aby łatwo wprowadzić funkcję do pliku CPP, zaznacz kursorem funkcję, która powinna mieć pod nią zieloną linię i wciśnij „Lewy ALT + ENTER”, co da ci możliwość utworzenia definicji w pliku CPP. plik CPP powiązany z klasami. Zobacz zdjęcie 6.1, aby zobaczyć, jak powinien wyglądać plik nagłówkowy, a po utworzeniu wszystkich definicji funkcji twój CPP powinien wyglądać jak zdjęcie 6.2, z wyjątkiem tego, że twoje definicje funkcji nie będą zawierały żadnego kodu.

Teraz będziesz chciał dodać ten sam kod, co na zdjęciu 6.2 do definicji funkcji. Jak wspomniano wcześniej, nasze funkcje publiczne będą korzystać z funkcji Instance(), która zwróci to, na co wskazuje ptrInstance. To pozwala nam na dostęp do prywatnych funkcji naszej klasy. W przypadku dowolnej funkcji publicznej singletona powinieneś wywoływać tylko tę funkcję Instance. Jedynym wyjątkiem jest nasza funkcja Terminate.

Uwaga: Dokładne funkcje publiczne i prywatne pokazane w tym kroku nie są konieczne, możesz mieć różne nazwy funkcji i operacje w funkcji prywatnej, ale dla każdego typu funkcji publicznej powinieneś mieć funkcję prywatną, która będzie do niej pasować i funkcja public powinna zawsze używać, w naszym przypadku, funkcji Instance().

Krok 7: Tworzenie funkcji zakończenia

Tworzenie funkcji zakończenia
Tworzenie funkcji zakończenia
Tworzenie funkcji zakończenia
Tworzenie funkcji zakończenia

Ponieważ w naszej klasie możemy tylko cofnąć alokację naszego singletona z pamięci, musimy utworzyć statyczną funkcję publiczną. Ta funkcja wywoła delete na ptrInstance, które wywołuje destruktor klasy, a następnie będziemy chcieli ustawić ptrInstance z powrotem na nullptr, aby można go było przydzielić ponownie, jeśli program się nie kończy. Będziesz także chciał zakończyć działanie swoich Singletonów, aby wyczyścić całą przydzieloną pamięć, którą przydzieliłeś w dowolnych prywatnych zmiennych Singletona.

Krok 8: Ustawienie PtrInstance na Nullptr

Ustawienie PtrInstance na Nullptr
Ustawienie PtrInstance na Nullptr

Aby ukończyć swój singleton, przejdź do pliku EngineDebugSingleton. CPP i na górze pliku CPP, w naszym przypadku, wpisz „EngineDebugSingleton* EngineDebugSingleton::ptrInstance = nullptr”.

Spowoduje to początkowo ustawienie ptrInstance na nullptr, więc kiedy po raz pierwszy przejdziesz przez funkcję instancji, nasza klasa będzie mogła zostać przydzielona do pamięci. Bez tego najprawdopodobniej otrzymasz błąd, ponieważ będziesz próbował uzyskać dostęp do pamięci, do której nic nie jest przydzielone.

Krok 9: Test i wnioski

Test i wnioski
Test i wnioski

Będziemy teraz chcieli przetestować, czy nasz singleton działa, będzie to wymagało od nas wywołania funkcji publicznych, jak opisano w kroku 6, i zalecamy ustawienie punktów przerwania, aby przejść przez kod i zobaczyć, że singleton działa jako powinno być. Naszym punktem wyjścia będzie main.cpp naszego projektu, a nasz main.cpp wygląda teraz tak, jak na poniższym obrazku.

Gratulacje! Właśnie zakończyłeś swoją pierwszą implementację Wzorca Projektowego Singleton. Dzięki temu wzorcowi projektowemu możesz teraz usprawnić swój kod na różne sposoby. Na przykład możesz teraz tworzyć systemy menedżerskie, które działają w czasie wykonywania programu, do których można uzyskać dostęp za pośrednictwem funkcji statycznych w dowolnym miejscu, w którym umieściłeś klasę.

Twój ostateczny plik nagłówkowy powinien wyglądać jak na zdjęciu 7.1. Plik CPP powiązany z Twoim singletonem powinien wyglądać jak zdjęcie 6.2 z dodatkiem, u góry pliku, kodu pokazanego w kroku 8. Ta instrukcja zapewniła ci prostą strukturę wzorca projektowego Singleton.

Porady dotyczące rozwiązywania problemów:

Otrzymujesz błędy związane z pamięcią?

Upewnij się, że odwołujesz się do kroku 7 i kroku 8, aby upewnić się, że ustawiasz ptrInstance na nullptr.

Występuje nieskończona pętla?

Upewnij się, że dla funkcji publicznych, w ich definicjach, wywołujesz funkcję prywatną, a nie tę samą funkcję publiczną.

Obiekty przydzielone w obrębie singletona powodujące wycieki pamięci?

Upewnij się, że w kodzie programu wywołujesz funkcję terminala swojego singletona, a w destruktorze swojego singletona, upewnij się, że cofniesz alokację wszystkich obiektów, które zostały przydzielone do pamięci w zakresie kodu singletona.