Menu
Coddy logo textTech

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.

challenge icon

Görev

Kolay

Bir 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.

    GameSettings sınıfınız üç ayarı özel üyeler olarak saklamalıdır: difficulty (string), volume (0-100 arası integer) ve fullscreen (boolean). Bunları varsayılan değerlerle başlatın: "Normal", 50 ve false.

    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ünceller
    • setVolume(int vol): ses seviyesini günceller
    • setFullscreen(bool fs): tam ekran modunu günceller
    • displaySettings(): 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 applyGamePreset adlı bir işlev tanımlayın. Bu işlev GameSettings singleton'ına erişmeli ve ön ayara göre yapılandırmalıdır:

    • "casual": zorluk seviyesini "Easy", ses seviyesini 70 ve tam ekranı false yapar
    • "competitive": zorluk seviyesini "Hard", ses seviyesini 30 ve tam ekranı true yapar
    • 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:

    1. Bir ön ayar adı (string)
    2. Ö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 applyGamePreset iş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: no

competitive ve 20 girdileriyle:

Difficulty: Normal
Volume: 50
Fullscreen: no

Difficulty: Hard
Volume: 30
Fullscreen: yes

Difficulty: Hard
Volume: 20
Fullscreen: yes

Hem 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;
}
quiz iconKendini test et

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

Kendi başına pratik yap: Online C++ derleyicisi