Apa itu lajang?
Singleton adalah salah satu pola desain paling sederhana yang dapat diterapkan pada suatu kelas. Terkadang orang mengatakan “kelas ini adalah kelas tunggal”, artinya kelas ini mengimplementasikan pola desain tunggal. Terkadang perlu untuk menulis kelas yang hanya dapat membuat satu objek. Misalnya, kelas yang bertanggung jawab untuk mencatat atau menghubungkan ke database. Pola desain Singleton menjelaskan bagaimana kita dapat menyelesaikan tugas tersebut. Singleton adalah pola desain yang melakukan dua hal:-
Memberikan jaminan bahwa suatu kelas hanya akan memiliki satu instance kelas tersebut.
-
Menyediakan titik akses global ke instance kelas ini.
-
Konstruktor swasta. Membatasi kemampuan untuk membuat objek kelas di luar kelas itu sendiri.
-
Metode statis publik yang mengembalikan turunan kelas. Metode ini disebut
getInstance
. Ini adalah titik akses global ke instance kelas.
Opsi implementasi
Pola desain tunggal digunakan dengan cara yang berbeda. Setiap pilihan baik dan buruk dengan caranya sendiri. Di sini, seperti biasa: tidak ada yang ideal, tetapi Anda harus berjuang untuk itu. Namun pertama-tama, mari kita definisikan apa yang baik dan apa yang buruk, dan metrik apa yang memengaruhi evaluasi penerapan pola desain. Mari kita mulai dengan hal positif. Berikut kriteria yang membuat pelaksanaannya menarik dan menarik:-
Inisialisasi lambat: ketika kelas dimuat saat aplikasi berjalan tepat pada saat dibutuhkan.
-
Kesederhanaan dan transparansi kode: metriknya tentu saja subjektif, tetapi penting.
-
Keamanan thread: berfungsi dengan benar di lingkungan multi-thread.
-
Kinerja tinggi dalam lingkungan multi-thread: thread saling memblokir secara minimal atau tidak sama sekali saat berbagi sumber daya.
-
Inisialisasi non-malas: ketika sebuah kelas dimuat saat aplikasi dimulai, terlepas dari apakah diperlukan atau tidak (paradoksnya, di dunia IT lebih baik bermalas-malasan)
-
Kompleksitas dan keterbacaan kode yang buruk. Metriknya juga subjektif. Kita asumsikan kalau keluar darah dari mata, pelaksanaannya biasa saja.
-
Kurangnya keamanan benang. Dengan kata lain, “bahaya benang”. Pengoperasian yang salah di lingkungan multi-utas.
-
Performa buruk dalam lingkungan multi-thread: thread saling memblokir sepanjang waktu atau sering kali saat berbagi sumber daya.
Kode
Sekarang kami siap mempertimbangkan berbagai opsi implementasi, dengan mencantumkan pro dan kontra:Solusi Sederhana
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return INSTANCE;
}
}
Implementasi paling sederhana. Kelebihan:
-
Kesederhanaan dan transparansi kode
-
Keamanan benang
-
Performa tinggi dalam lingkungan multi-thread
- Bukan inisialisasi yang malas.
Inisialisasi Malas
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {}
public static Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
Kelebihan:
-
Inisialisasi malas.
-
Tidak aman untuk benang
Aksesor Tersinkronisasi
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {
}
public static synchronized Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
Kelebihan:
-
Inisialisasi malas.
-
Keamanan benang
-
Performa buruk di lingkungan multi-thread
getInstance
sudah tersinkronisasi, dan Anda hanya dapat memasukkannya satu per satu. Faktanya, kita tidak perlu menyinkronkan seluruh metode, tetapi hanya bagian di mana kita menginisialisasi objek kelas baru. Tapi kita tidak bisa begitu saja membungkus synchronized
bagian yang bertanggung jawab untuk membuat objek baru dalam satu blok: ini tidak akan memberikan keamanan thread. Ini sedikit lebih rumit. Metode sinkronisasi yang benar diberikan di bawah ini:
Penguncian Diperiksa Ganda
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {
}
public static Singleton getInstance() {
if (INSTANCE == null) {
synchronized (Singleton.class) {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
Kelebihan:
-
Inisialisasi malas.
-
Keamanan benang
-
Performa tinggi dalam lingkungan multi-thread
-
Tidak didukung pada versi Java yang lebih rendah dari 1.5 (kata kunci volatil telah diperbaiki di versi 1.5)
INSTANCE
harus berupa final
, atau volatile
. Implementasi terakhir yang akan kita bahas hari ini adalah Class Holder Singleton
.
Pemegang Kelas Singleton
public class Singleton {
private Singleton() {
}
private static class SingletonHolder {
public static final Singleton HOLDER_INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.HOLDER_INSTANCE;
}
}
Kelebihan:
-
Inisialisasi malas.
-
Keamanan benang.
-
Performa tinggi dalam lingkungan multi-thread.
-
Untuk pengoperasian yang benar, perlu adanya jaminan bahwa objek kelas
Singleton
diinisialisasi tanpa kesalahan. Jika tidak, pemanggilan metode pertamagetInstance
akan berakhir dengan kesalahanExceptionInInitializerError
, dan semua pemanggilan metode berikutnya akan gagalNoClassDefFoundError
.
Penerapan | Inisialisasi malas | Keamanan benang | Kecepatan multithread | Kapan digunakan? |
---|---|---|---|---|
Solusi Sederhana | - | + | Cepat | Tidak pernah. Atau ketika inisialisasi malas tidak penting. Tapi tidak pernah lebih baik. |
Inisialisasi Malas | + | - | Tak dapat diterapkan | Selalu ketika multithreading tidak diperlukan |
Aksesor Tersinkronisasi | + | + | Perlahan-lahan | Tidak pernah. Atau ketika kecepatan bekerja dengan multithreading tidak menjadi masalah. Tapi tidak pernah lebih baik |
Penguncian Diperiksa Ganda | + | + | Cepat | Dalam kasus yang jarang terjadi ketika Anda perlu menangani pengecualian saat membuat singleton. (ketika Class Holder Singleton tidak berlaku) |
Pemegang Kelas Singleton | + | + | Cepat | Selalu ketika multithreading diperlukan dan ada jaminan bahwa objek kelas tunggal akan dibuat tanpa masalah. |
Pro dan kontra dari pola Singleton
Secara umum, singleton melakukan apa yang diharapkan:-
Memberikan jaminan bahwa suatu kelas hanya akan memiliki satu instance kelas tersebut.
-
Menyediakan titik akses global ke instance kelas ini.
-
Singleton melanggar SRP (Prinsip Tanggung Jawab Tunggal) - kelas Singleton, selain tanggung jawab langsungnya, juga mengontrol jumlah salinannya.
-
Ketergantungan kelas reguler atau metode pada singleton tidak terlihat dalam kontrak publik kelas tersebut.
-
Variabel global itu buruk. Singleton pada akhirnya berubah menjadi satu variabel global yang besar dan kuat.
-
Kehadiran singleton mengurangi kemampuan pengujian aplikasi secara umum dan kelas yang menggunakan singleton pada khususnya.
GO TO FULL VERSION