Menu
Coddy logo textTech

Singleton Kalıbı

Coddy'nin Python Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 45 / 64.

Singleton kalıbı, bir sınıfın yalnızca bir örneğe sahip olmasını ve bu örneğe küresel bir erişim noktası sağlamasını garanti eder. Bu, veritabanı bağlantıları veya yapılandırma ayarları gibi kaynaklar için kullanışlıdır.

İşte temel bir Singleton uygulaması:

class Singleton:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

__new__ yöntemi nesne oluşturmayı denetler. Yeni bir örnek oluşturmadan önce zaten bir örneğin var olup olmadığını kontrol eder.

Singleton sınıfının iki örneğini oluşturun:

singleton1 = Singleton()
singleton2 = Singleton()

Her iki değişkenin de aynı nesneye başvurup başvurmadığını kontrol edin:

print(singleton1 is singleton2)  # True
print(id(singleton1))            # Aynı bellek adresi
print(id(singleton2))            # Aynı bellek adresi

Veritabanı bağlantısı içeren daha pratik bir örnek:

class DatabaseConnection:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance.connection = "Connected to MySQL database"
            print("Creating new database connection")
        return cls._instance
    
    def query(self, sql):
        return f"Executing: {sql}"

# İlk erişim bağlantıyı oluşturur
db1 = DatabaseConnection()
print(db1.connection)

# İkinci erişim aynı bağlantıyı yeniden kullanır
db2 = DatabaseConnection()
print(db2.connection)

print(db1.query("SELECT * FROM users"))
print(db1 is db2)

Singleton kullanarak bir konfigürasyon yöneticisi oluşturun:

class Config:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            cls._instance.settings = {}
        return cls._instance
    
    def set_setting(self, key, value):
        self.settings[key] = value
    
    def get_setting(self, key):
        return self.settings.get(key)

config1 = Config()
config1.set_setting("debug", True)

config2 = Config()
print(config2.get_setting("debug"))  # True - aynı ayarlar

Çıktı:

True
140234567890123
140234567890123
Creating new database connection
Connected to MySQL database
Connected to MySQL database
Executing: SELECT * FROM users
True
True

Önemli Nokta: Singleton deseni, nesne oluşturmayı kontrol etmek ve yalnızca bir örneğin var olmasını sağlamak için __new__ kullanır. Veritabanı bağlantıları, günlükleyiciler veya yapılandırma yöneticileri gibi uygulamanız boyunca yalnızca bir kopyaya sahip olması gereken kaynaklar için kullanın. Singleton'a işaret eden tüm değişkenlerin bellekte aynı nesneye başvurduğunu unutmayın.

challenge icon

Görev

Kolay

Bu görevde, bir veritabanı bağlantısı sınıfı için Singleton tasarım desenini uygulayacaksınız.

  • TODO yorumlarını takip ederek Singleton desenini uygulamak için databaseconnection.py dosyasını düzenleyin
  • driver.py dosyası kapsamlı test senaryoları içerir ve değiştirilmemelidir

Kendin dene

from databaseconnection import DatabaseConnection

# Kapsamlı test durumu işleyicisi
test_case = input()

if test_case == "identity_check":
    db1 = DatabaseConnection()
    db2 = DatabaseConnection()
    print(db1 is db2)  # True yazdırmalı

elif test_case == "connect_state":
    db = DatabaseConnection()
    print(f"Initial connected state: {db.connected}")  # False yazdırmalı
    db.connect()
    print(f"After connect: {db.connected}")  # True yazdırmalı

elif test_case == "disconnect_state":
    db = DatabaseConnection()
    db.connect()
    db.disconnect()
    print(f"After disconnect: {db.connected}")  # False yazdırmalı

elif test_case == "multiple_instances_same_state":
    db1 = DatabaseConnection()
    db1.connect()
    db2 = DatabaseConnection()
    print(f"db2 connected state: {db2.connected}")  # True yazdırmalı

elif test_case == "host_value":
    db = DatabaseConnection()
    print(f"Default host: {db.host}")  # "localhost" yazdırmalı
    db.host = "new-server"
    db2 = DatabaseConnection()
    print(f"New instance host: {db2.host}")  # "new-server" yazdırmalı

elif test_case == "init_once":
    db1 = DatabaseConnection()
    db1.host = "custom-host"
    db2 = DatabaseConnection()
    print(f"Both instances have same host: {db1.host == db2.host}")  # True yazdırmalı
    print(f"Host value: {db1.host}")  # "custom-host" yazdırmalı

elif test_case == "connect_message":
    db = DatabaseConnection()
    db.connect()  # Should print "Connected to database at localhost"

elif test_case == "disconnect_message":
    db = DatabaseConnection()
    db.connect()
    db.disconnect()  # Should print "Disconnected from database"

elif test_case == "attribute_modification":
    db1 = DatabaseConnection()
    db1.port = 3306
    db2 = DatabaseConnection()
    print(f"db2 has port attribute: {hasattr(db2, 'port')}")  # True yazdırmalı
    print(f"db2 port value: {db2.port}")  # 3306 yazdırmalı

elif test_case == "reset_connection":
    db1 = DatabaseConnection()
    db1.connect()
    print(f"Connected state: {db1.connected}")  # True yazdırmalı
    db2 = DatabaseConnection()
    print(f"New instance connected state: {db2.connected}")  # True yazdırmalı
    db2.disconnect()
    db3 = DatabaseConnection()
    print(f"After disconnect, new instance state: {db3.connected}")  # False yazdırmalı

elif test_case == "multiple_connects":
    db = DatabaseConnection()
    db.connect()
    db.connect()
    db.connect()
    print(f"Connected state after multiple connects: {db.connected}")  # True yazdırmalı
    db.disconnect()
    print(f"Connected state after disconnect: {db.connected}")  # False yazdırmalı

elif test_case == "host_change_affects_message":
    db = DatabaseConnection()
    db.host = "custom-server"
    db.connect()  # Will still print "Connected to database at localhost"
    # connect metodunun host özniteliğini kullanmayan sabit kodlanmış bir mesajı vardır
    print("Message still shows localhost: True")
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 Python derleyicisi