Menu
Coddy logo textTech

Singleton Kalıbı

Coddy'nin PHP Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 71 / 91.

Singleton Deseni, bir sınıfın uygulamanızın yaşam döngüsü boyunca yalnızca bir örneğe sahip olmasını sağlayan bir oluşturucu tasarım desenidir. Ayrıca bu örneğe küresel bir erişim noktası sağlar.

Bu desen; veritabanı bağlantısı, yapılandırma yöneticisi veya günlükçü (logger) gibi sistem genelindeki eylemleri koordine etmek için tam olarak bir nesneye ihtiyaç duyduğunuzda yararlıdır. Bunlardan birden fazla örnek oluşturmak, kaynak israfına yol açar veya tutarsız davranışlara neden olur.

PHP'de bir Singleton'ın nasıl uygulanacağı aşağıda açıklanmıştır:

<?php
class Database {
    private static ?Database $instance = null;
    
    private function __construct() {
        // Özel kurucu metot, doğrudan örnek oluşturulmasını engeller
    }
    
    public static function getInstance(): Database {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    public function query(string $sql): string {
        return "Executing: $sql";
    }
}

$db1 = Database::getInstance();
$db2 = Database::getInstance();

echo $db1 === $db2 ? "Same instance" : "Different instances";

Çıktı:

Same instance

Desen üç temel öğeye dayanır: new anahtar kelimesinin doğrudan kullanılmasını engelleyen bir özel yapıcı, tek örneği tutan bir statik özellik ve ilk çağrıda örneği oluşturan, sonraki çağrılarda ise bu örneği döndüren bir statik metot.

Singleton'ı gerçekten kurşun geçirmez hale getirmek için, klonlamayı ve serileştirmeyi (unserialization) de engellemelisiniz:

<?php
private function __clone() {}
public function __wakeup() {
    throw new Exception("Cannot unserialize singleton");
}
challenge icon

Görev

Kolay

Singleton Tasarım Kalıbını kullanarak bir yapılandırma yöneticisi (configuration manager) oluşturalım. Gerçek uygulamalarda, yapılandırma ayarları için genellikle tek bir doğruluk kaynağı istersiniz; birden fazla yapılandırma nesnesine sahip olmak, sisteminizde tutarsız davranışlara yol açabilir.

Kodunuzu iki dosya halinde düzenleyeceksiniz:

  • Config.php — Singleton Tasarım Kalıbını uygulayan bir Config sınıfı oluşturun. Yapılandırma yöneticiniz şunları yapmalıdır:
    • Ayarları özel (private) bir dizi (array) özelliğinde saklamalıdır
    • Ayarlar dizisini boş olarak başlatan özel (private) bir yapıcı metoda (constructor) sahip olmalıdır
    • Tek örneği döndüren statik bir getInstance() metodu sağlamalıdır
    • __clone() metodunu özel (private) yaparak kopyalamayı (cloning) engellemelidir
    • Bir ayarı saklamak için bir set(string $key, string $value): void metodu içermelidir
    • Bir anahtarın değerini döndüren veya anahtar mevcut değilse null döndüren bir get(string $key): ?string metodu içermelidir
    • Tüm ayarları döndüren bir getAll(): array metodu içermelidir
  • main.php — Config dosyasını dahil edin. İki girdi alacaksınız: bir anahtar (key) ve bir değer (value).

    Config örneğini alın ve anahtarı "app_name", değeri "MyApp" olan varsayılan bir ayar atayın.

    Config örneğine ikinci bir referans alın (tekrar getInstance() kullanarak) ve bunu, girdilerden gelen anahtar ve değeri kullanarak başka bir ayar atamak için kullanın.

    Son olarak, Singleton'ın doğru çalışıp çalışmadığını doğrulayın:

    • Her iki referansın da aynı nesneyi işaret edip etmediğine bağlı olarak "Same instance: true" veya "Same instance: false" yazdırın (karşılaştırmak için === kullanın)
    • Saklanan toplam ayar sayısını gösteren "Settings count: [count]" yazdırın (getAll() sonucunda count() kullanın)
    • İkinci referans aracılığıyla alınan app_name ayarını gösteren "App name: [value]" yazdırın

Bu zorluk, Singleton Tasarım Kalıbının temel faydasını göstermektedir: getInstance() metodunu kaç kez çağırırsanız çağırın, her zaman aynı nesneyi alırsınız ve bu da uygulamanızın tüm bölümlerinin aynı yapılandırma durumunu paylaşmasını sağlar.

Kopya kağıdı

Singleton Deseni, bir sınıfın uygulamanızın yaşam döngüsü boyunca yalnızca bir örneğe sahip olmasını sağlar ve bu örneğe küresel bir erişim noktası sunar.

Bu desen; veritabanı bağlantıları, yapılandırma yöneticileri veya günlükçüler (loggers) gibi, birden fazla örneğin kaynak israfına yol açacağı veya tutarsız davranışlara neden olacağı nesneler için kullanışlıdır.

Temel Singleton uygulaması:

<?php
class Database {
    private static ?Database $instance = null;
    
    private function __construct() {
        // Özel yapıcı metot doğrudan örneklemeyi engeller
    }
    
    public static function getInstance(): Database {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
}

$db1 = Database::getInstance();
$db2 = Database::getInstance();

echo $db1 === $db2 ? "Same instance" : "Different instances";
// Çıktı: Same instance

Temel öğeler:

  • Özel yapıcı metot (Private constructor)new anahtar kelimesinin doğrudan kullanılmasını engeller
  • Statik özellik (Static property) — tek örneği tutar
  • Statik metot (Static method) — ilk çağrıda örneği oluşturur ve sonraki çağrılarda bu örneği döndürür

Klonlamayı ve serileştirmeyi (unserialization) engelleme:

<?php
private function __clone() {}

public function __wakeup() {
    throw new Exception("Cannot unserialize singleton");
}

Kendin dene

<?php

require_once 'Config.php';

// Girdiyi oku
$key = trim(fgets(STDIN));
$value = trim(fgets(STDIN));

// TODO: Config örneğini (instance) alın ve "app_name" değerini "MyApp" olarak ayarlayın

// TODO: getInstance() yöntemini tekrar kullanarak Config'e ikinci bir referans alın

// TODO: İkinci referansı kullanarak, girdiden gelen $key ve $value değerleriyle ayarı yapın

// TODO: Singleton'ın çalıştığını doğrulayın:
// - === karşılaştırmasına dayanarak "Same instance: true" veya "Same instance: false" yazdırın
// - Toplam ayar sayısını gösteren "Settings count: [count]" yazdırın
// - İkinci referans aracılığıyla alınan app_name değerini gösteren "App name: [value]" yazdırın

?>
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