Singleton Kalıbı
Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 91 / 104.
Singleton deseni, bir sınıfın programın tamamı boyunca yalnızca bir örneğe sahip olmasını ve bu örneğe küresel bir erişim noktası sunmasını sağlar. Bu, yapılandırma yöneticisi, günlükleyici veya veritabanı bağlantı havuzu gibi paylaşılması gereken kaynaklar için kullanışlıdır.
Temel fikir, kurucuyu private yaparak kimsenin doğrudan örnek oluşturamamasını sağlamak ve ardından tek örneği döndüren bir static metot sunmaktır:
#include <iostream>
#include <string>
class Logger {
private:
std::string logFile;
// Private constructor - doğrudan örneklemeyi engeller
Logger() : logFile("app.log") {}
// Copy constructor ve assignment operator'ü sil
Logger(const Logger&) = delete;
Logger& operator=(const Logger&) = delete;
public:
// Tek örneğe erişmek için static metot
static Logger& getInstance() {
static Logger instance; // Bir kez oluşturulur, program sonuna kadar yaşar
return instance;
}
void log(const std::string& message) {
std::cout << "[LOG] " << message << "\n";
}
};
int main() {
Logger::getInstance().log("Application started");
Logger& logger = Logger::getInstance();
logger.log("Processing data");
}getInstance() içindeki static Logger instance, "sihirli statikler" olarak adlandırılan bir C++11 özelliğidir; iş parçacığı açısından güvenlidir ve yalnızca bir kez başlatılması garanti edilir. Kopya oluşturucuyu ve atama operatörünü silerek, herhangi birinin singleton'ımızın kopyalarını oluşturmasını önleriz.
Singleton'ı ölçülü kullanın - test etmeyi zorlaştırabilecek küresel durum sunar. Birden fazla örneğe sahip olmanın sorunlara yol açacağı gerçekten paylaşılan kaynaklar için en uygunudur.
Görev
KolayBir oyun uygulamasının yapılandırmasını yöneten bir GameSettings singleton'ı oluşturalım. Bu, Singleton deseni için mükemmel bir kullanım alanıdır. Oyununuzun tüm bölümlerinin erişebileceği tam olarak bir ayar yöneticisi isteyerek yapılandırmanın her yerde tutarlı olmasını sağlarsınız.
Kodunuzu üç dosyada düzenleyeceksiniz:
GameSettings.h: Oyun yapılandırmasını yöneten singleton sınıfınızı tanımlayın.GameSettingssınıfınız üç ayarı özel üyeler olarak saklamalıdır:difficulty(string),volume(0-100 arası integer) vefullscreen(boolean). Bunları varsayılan değerlerle başlatın:"Normal",50vefalse.Singleton desenini doğru şekilde uygulayın:
- Oluşturucuyu private yapın
- Kopya oluşturucuyu ve atama operatörünü silin
- Tek örneğe başvuru döndüren statik bir
getInstance()metodu sağlayın
Ayarlarla etkileşim kurmak için şu public metotları ekleyin:
setDifficulty(const std::string& diff): zorluk seviyesini güncellersetVolume(int vol): ses seviyesini güncellersetFullscreen(bool fs): tam ekran modunu güncellerdisplaySettings(): mevcut tüm ayarları yazdırır
GameModule.h: Singleton'a erişen ayrı bir modül oluşturun.Bir ön ayar adı (string) alan
applyGamePresetadlı bir işlev tanımlayın. Bu işlevGameSettingssingleton'ına erişmeli ve ön ayara göre yapılandırmalıdır:"casual": zorluk seviyesini"Easy", ses seviyesini70ve tam ekranıfalseyapar"competitive": zorluk seviyesini"Hard", ses seviyesini30ve tam ekranıtrueyapar- Diğer tüm ön ayarlar: varsayılan ayarları değiştirmeden bırakır
Bu, bir programın farklı bölümlerinin aynı singleton örneğine nasıl erişip onu değiştirebileceğini gösterir.
main.cpp: Singleton'ın çalışırken nasıl kullanıldığını göstermek için her şeyi bir araya getirin.İki girdi okuyun:
- Bir ön ayar adı (string)
- Özel bir ses seviyesi (integer)
Öncelikle singleton üzerinde
displaySettings()çağırarak başlangıçtaki varsayılan ayarları görüntüleyin. Ardından boş bir satır yazdırın.Sonra
applyGamePresetişlevinizi kullanarak ön ayarı uygulayın ve ayarları tekrar görüntüleyin. Ardından boş bir satır yazdırın.Son olarak yalnızca ses seviyesini özel girdi değeriyle geçersiz kılın ve son ayarları görüntüleyin.
displaySettings() metodu tam olarak şu biçimde çıktı vermelidir:
Difficulty: [value]
Volume: [value]
Fullscreen: [yes/no]Örneğin, casual ve 85 girdileriyle:
Difficulty: Normal
Volume: 50
Fullscreen: no
Difficulty: Easy
Volume: 70
Fullscreen: no
Difficulty: Easy
Volume: 85
Fullscreen: nocompetitive ve 20 girdileriyle:
Difficulty: Normal
Volume: 50
Fullscreen: no
Difficulty: Hard
Volume: 30
Fullscreen: yes
Difficulty: Hard
Volume: 20
Fullscreen: yesHem main.cpp hem de GameModule.h aynı singleton örneğine erişir: bir yerde yapılan değişiklikler her yerde görünür. Bu, oyun ayarları gibi paylaşılan kaynaklar için Singleton deseninin gücüdür.
Kendin dene
#include <iostream>
#include <string>
#include "GameSettings.h"
#include "GameModule.h"
using namespace std;
int main() {
// Girdileri oku
string presetName;
int customVolume;
cin >> presetName;
cin >> customVolume;
// TODO: GameSettings singleton örneğini al
// TODO: İlk varsayılan ayarları görüntüle
// TODO: Boş bir satır yazdır
// TODO: applyGamePreset fonksiyonunu kullanarak ön ayarı uygula
// TODO: Ön ayarı uyguladıktan sonra ayarları görüntüle
// TODO: Boş bir satır yazdır
// TODO: Ses seviyesini customVolume ile geçersiz kıl
// TODO: Son ayarları görüntüle
return 0;
}
Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.
Nesne Yönelimli Programlama bölümündeki tüm dersler
1OOP Temelleri
Harici DosyalarC++ Build ve DerlemeBaşlık Dosyaları ve Kaynak DosyalarıAd Alanları ve KapsamC++'ta OOP'ye GirişSınıflar ve Nesneler'this' İşaretçisiMetotlar (Üye Fonksiyonlar)Öznitelikler (Veri Üyeleri)Ctor ve Dtor TemelleriÖzet - Basit Hesap Makinesi4Sınıf Özellikleri
Örnek ve Statik ÜyelerGetter ve Setter MetotlarıConst Üye FonksiyonlarMutable Anahtar KelimesiStatik Metotlar ve DeğişkenlerFriend Fonksiyonlar ve SınıflarÖzet - Banka Hesabı Yöneticisi7Kalıtım
Temel KalıtımKalıtım Erişim SeviyeleriCtor ve Dtor Çağrılma SırasıMetot Geçersiz KılmaSanal Fonksiyonlar ve VTableÇoklu KalıtımSanal KalıtımÖzet - Çalışan Hiyerarşisi10STL Genel Bakış
STL Genel Bakış ve FelsefesiSTL KonteynerleriİteratörlerSTL AlgoritmalarıFunctor'lar ve Lambda İfadeleriÖzet - Kelime Frekansı13Tasarım Kalıpları 1. Bölüm
Tasarım Kalıplarına GirişSingleton KalıbıFactory ve Abstract FactoryBuilder KalıbıObserver KalıbıStrategy Kalıbı2Bellek Yönetimi
Stack ve Heap Bellekİşaretçiler ve ReferanslarDinamik Bellek (new/delete)C++'ta Akıllı İşaretçilerC++'ta RAIIÖzet - Dinamik Dizi Yöneticisi5Kapsülleme
C++'da Erişim BelirleyicilerDerinlemesine Erişim BelirleyicilerBilgi GizlemeStruct vs Classİç İçe ve Dahili SınıflarÖzet - Öğrenci Kayıt Sistemi8Çok Biçimlilik
Derleme ve Çalışma Zamanı Çok BiçimliliğiFonksiyon Aşırı YüklemeSanal Fonksiyonlara Yeniden BakışSaf Sanal FonksiyonlarSoyut SınıflarC++'ta Arayüz TasarımıDynamic Casting ve RTTIÖzet - Şekil Hesaplayıcı3Yapıcılar ve Yıkıcılar
Varsayılan YapıcıParametreli YapıcıKopya YapıcıTaşıma YapıcısıYapıcı İlklendirme ListeleriTemsilci YapıcılarYıkıcılara Derinlemesine BakışÜç / Beş / Sıfır KuralıÖzet - String Sınıfı6Operatör Aşırı Yükleme
Operatör Aşırı Yüklemeye GirişAritmetik Operatör Aşırı YüklemeKarşılaştırma Operatörü Aşırı YüklemeStream OperatörleriAtama Operatörü Aşırı Yükleme[] ve () Operatör Aşırı YüklemeTip Dönüşüm OperatörleriÖzet - Matris Sınıfı9Şablonlar
Fonksiyon ŞablonlarıSınıf ŞablonlarıŞablon ÖzelleştirmeVariadic ŞablonlarSFINAE ve Type Traits TemelleriÖzet - Generic KonteynerKendi başına pratik yap: Online C++ derleyicisi