Skip to the content.

Singleton

Main PageCreational PatternsSingleton

Source Code refactoring.guru sourcemaking.com

Singleton

The most basic & simplest type of creational design pattern. Just define a private constructor & call for a instance to define a object.

Singleton merupakan design pattern yang paling sederhana yang bertujuan untuk membatasi deklarasi menjadi hanya 1 instance/object dalam sebuah class. Dalam Singleton, hanya ada 1 object dari class tersebut yang dapat dibuat untuk class client, yaitu instance itu sendiri. Setiap pemanggilan object berikutnya yang dilakukan oleh client, object akan dipanggilkan langsung dari instance yang sudah dibuatkan oleh class tersebut.

Singleton menggunakan lazy-loading untuk menginisiasikan sebuah instance/object dalam sebuah class yang hanya dipanggil 1x sejak class tersebut dipanggil oleh class client untuk mencegah borosnya resource yang terjadi karena pemanggilan object yang berulang-ulang.

Sederhananya, client tidak bisa membuat object dari suatu class lebih dari 1 kali & tidak mempunyai constructor (karena access modifier yang private), sebaliknya object tersebut kemudian memanggil instance/object pertama sudah dibuatkan oleh class tersebut.

Implementasi

UML Model

Singleton

Contoh code

Dalam kasus Singleton, kita merancang bentuk paling sederhana dari Singleton sebagai berikut:

public class MySingleton {
  private MySingleton() {
    // TODO contents of constructor (if needed)
  }

  private static MySingleton instance = null;

  public static MySingleton getInstance() {
    if (instance == null) {
      instance = new MySingleton();
    }
    return instance;
  }

  // TODO declaration and methods here...
}

Dalam kasus multithreading, penggunaan Singleton dengan bentuk paling dasar sendiri tidaklah cukup apabila kita harus menghadapi banyak thread yang menggunakan Singleton tersebut sehingga dalam class tersebut dapat ditambahkan keyword volatile kepada object Singleton, instance untuk menampung variabel tersebut langsung ke main memory dan synchronized kepada method getInstance() untuk menjamin bahwa proses pengambilan instance tersebut thread-safe.

Hasil implementasi Singleton dalam kasus multithreading adalah sebagai berikut:

public class MySingleton {
  private MySingleton() {
    // TODO contents of constructor (if needed)
  }

  private volatile static MySingleton instance = null;

  public static synchronized MySingleton getInstance() {
    if (instance == null) {
      instance = new MySingleton();
    }
    return instance;
  }

  // TODO declaration and methods here...
}

Hal tersebut juga ikut turut serta dalam implementasi kasus Singleton yaitu class Storage, dimana class tersebut menampung data-data produknya dalam Vector<> untuk menjamin ketersediaan produk dengan menggunakan kasus multithreading, seluruh deklarasi Singleton dideklarasikan dengan keyword synchronized pada method dan volatile pada static attribute.

public class Storage {
  private Storage() {}

  /**
   * An instance for Storage, initially to be null before client class invoke to define this object for first time!
   * For next declarations, it will return this object defined from this class since first declaration.
   */
  private volatile static Storage instance = null;

  public static synchronized Storage getInstance() {
    if (instance == null)
       instance = new Storage();
    return instance;
  }

  private Vector<Product> storedProducts;

  // beyond methods and declaration codes inside...

}

Jenis-jenis Singleton

1. Eagerly-initialized Singleton

public class MySingleton {
  private static MySingleton instance = new MySingleton();

  private MySingleton() {
    // TODO contents of constructor (if needed)
  }

  public static MySingleton getInstance() {
    return instance;
  }

  // TODO declaration and methods here...
}

Jenis Singleton ini merupakan jenis singleton termudah, hanya dengan mendeklarasikan object langsung pada static attribute tanpa harus melalui null checking dimana method getInstance() hanya memanggil object instance pada class Singleton.

Jenis ini kurang efektif apabila class yang dibuatkan Singleton hanya dipanggil apabila dibutuhkan oleh class client dan mengakibatkan pemborosan resources dibanding dengan lazy initialization.

Namun dari segi pembuatan object, object tersebut sudah dibuatkan langsung oleh JVM sesaat class tersebut dipanggil & sebelum thread mengakses object/instance tersebut sehingga dijamin thread-safe dibanding melalui lazy initialization.

2. Lazy-initialized Singleton

public class MySingleton {
  private MySingleton() {
    // TODO contents of constructor (if needed)
  }

  private static MySingleton instance = null;

  public static MySingleton getInstance() {
    if (instance == null) {
      instance = new MySingleton();
    }
    return instance;
  }

  // TODO declaration and methods here...
}

Jenis Singleton ini mencakup deklarasi object dengan lazy initialization dimana object akan dibuatkan apabila belum ada. Sebaliknya, class akan memanggil instance yang sudah dibuatkan sebelumnya sebagai objectnya.

Jenis ini tidak akan berjalan efektif apabila class memerlukan aktivitas yang melibatkan beberapa thread atau ingin menjamin bahwa Singleton tersebut dapat berjalan efektif dalam kasus multithreading.

3. Thread-Safe Singleton

public class MySingleton {
  private MySingleton() {
    // TODO contents of constructor (if needed)
  }

  private volatile static MySingleton instance = null;

  public static synchronized MySingleton getInstance() {
    if (instance == null) {
      instance = new MySingleton();
    }
    return instance;
  }

  // TODO declaration and methods here...
}

Jenis Singleton ini menggunakan keyword volatile kepada object Singleton, instance untuk menampung variabel tersebut langsung ke main memory dan synchronized kepada method getInstance() untuk menjamin bahwa proses pengambilan instance tersebut thread-safe.

Jenis ini menjamin bahwa pembuatan object Singleton hanya sekali untuk semua thread yang menggunakan object tersebut & efektif dalam kasus multithreading.

4. Double-check Locking Singleton

public class MySingleton {
  private MySingleton() {
    // TODO contents of constructor (if needed)
  }

  private volatile static MySingleton instance = null;

  public static MySingleton getInstance() {
    if (instance == null) {
      synchronized(MySingleton.class) {
        if (instance == null) {
          instance = new MySingleton();
        }
      }
    }
    return instance;
  }

  // TODO declaration and methods here...
}

Merupakan implementasi lanjutan dari thread-safe Singleton, namun peletakan synchronized ditempatkan dalam method body getInstance() dalam null check untuk meminimalisir panggilan sinkronisasi thread berulang ketika memanggil instance object, sehingga sinkronisasi hanya dipakai apabila belum ada object instance pada class tersebut.

Selain itu, metode ini mengecek keberadaan object/instance Singleton sebanyak 2 kali, yaitu ketika method getInstance() dipanggil & dalam method body synchronized() pada static method getInstance().

Singleton ini menggunakan synchronized() dalam block pada static method getInstance() dimana apabila tidak ada object instance pada class tersebut, maka hanya 1 thread dalam class tersebut yang dapat mengakses isi method body synchronized() untuk dicek keberadaan object tersebut & dideklarasikan object/instance Singleton apabila benar-benar kosong.

Catatan Tambahan

Referensi