Menu
CoddyTech

Pola Singleton

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Python di Coddy. Pelajaran 45 dari 64.

Pola Singleton memastikan sebuah class hanya memiliki satu instance dan menyediakan titik akses global ke instance tersebut. Pola ini berguna untuk sumber daya seperti koneksi database atau pengaturan konfigurasi.

Berikut implementasi Singleton dasar:

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

Method __new__ mengontrol pembuatan object. Method ini memeriksa apakah instance sudah ada sebelum membuat instance baru.

Buat dua instance dari class Singleton:

singleton1 = Singleton()
singleton2 = Singleton()

Periksa apakah kedua variabel merujuk ke object yang sama:

print(singleton1 is singleton2)  # True
print(id(singleton1))            # Alamat memori yang sama
print(id(singleton2))            # Alamat memori yang sama

Berikut contoh yang lebih praktis dengan koneksi database:

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}"

# Akses pertama membuat koneksi
db1 = DatabaseConnection()
print(db1.connection)

# Akses kedua menggunakan kembali koneksi yang sama
db2 = DatabaseConnection()
print(db2.connection)

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

Buat pengelola konfigurasi menggunakan Singleton:

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, settings yang sama

Keluaran:

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

Poin utama: Pola Singleton menggunakan __new__ untuk mengendalikan pembuatan object, sehingga hanya ada satu instance. Gunakan pola ini untuk sumber daya yang hanya boleh memiliki satu salinan di seluruh aplikasi, seperti koneksi database, logger, atau pengelola konfigurasi. Ingat, semua variabel yang merujuk ke Singleton mengacu pada object yang sama di memori.

challenge icon

Tantangan

Mudah

Dalam tantangan ini, kamu akan menerapkan pola desain Singleton untuk class koneksi database.

  • Edit databaseconnection.py untuk menerapkan pola Singleton sesuai dengan komentar TODO
  • File driver.py berisi berbagai skenario pengujian dan tidak boleh diubah

Coba sendiri

from databaseconnection import DatabaseConnection

# Penangan kasus uji yang lengkap
test_case = input()

if test_case == "identity_check":
    db1 = DatabaseConnection()
    db2 = DatabaseConnection()
    print(db1 is db2)  # Seharusnya mencetak True

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

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

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

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

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

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

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

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

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

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

elif test_case == "host_change_affects_message":
    db = DatabaseConnection()
    db.host = "custom-server"
    db.connect()  # Tetap akan mencetak "Connected to database at localhost"
    # method connect memiliki pesan tetap yang tidak menggunakan atribut host
    print("Message still shows localhost: True")
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Compiler Python online