CodeGym /Java Blog /Acak /Kelas Tunggal Jawa
John Squirrels
Level 41
San Francisco

Kelas Tunggal Jawa

Dipublikasikan di grup Acak
Hai! Hari ini kita akan mendalami detail berbagai pola desain, dimulai dengan pola Java Singleton. Mari kita ulas: apa yang kita ketahui tentang design pattern secara umum? Pola desain adalah praktik terbaik yang dapat kita terapkan untuk memecahkan sejumlah masalah yang diketahui. Pola desain umumnya tidak terikat dengan bahasa pemrograman apa pun. Anggap saja sebagai serangkaian rekomendasi untuk membantu Anda menghindari kesalahan dan menghindari menciptakan kembali roda.Pola desain: Singleton - 1

Apa itu singleton di Jawa?

Singleton adalah salah satu pola desain tingkat kelas yang paling sederhana. Kadang-kadang orang mengatakan "kelas ini tunggal", yang berarti bahwa kelas mengimplementasikan pola desain tunggal. Kadang-kadang perlu untuk menulis sebuah kelas di mana kita membatasi instantiasi ke objek tunggal. Misalnya, kelas yang bertanggung jawab untuk masuk atau menghubungkan ke database. Pola desain singleton menjelaskan bagaimana kita bisa mencapainya. Singleton adalah pola desain yang melakukan dua hal:
  1. Ini menjamin bahwa hanya akan ada satu instance kelas.

  2. Ini memberikan satu titik akses global ke instans itu.

Oleh karena itu, ada dua fitur yang merupakan karakteristik dari hampir setiap penerapan pola singleton:
  1. Seorang konstruktor pribadi. Ini membatasi kemampuan untuk membuat objek kelas di luar kelas itu sendiri.

  2. Metode statis publik yang mengembalikan instance kelas. Metode ini disebut getInstance . Ini adalah titik akses global ke instance kelas.

Opsi implementasi

Pola desain singleton diterapkan dalam berbagai cara. Setiap opsi baik dan buruk dengan caranya sendiri. Seperti biasa, tidak ada pilihan yang sempurna di sini, tetapi kita harus berusaha untuk itu. Pertama-tama, mari kita putuskan apa yang baik dan buruk, dan metrik apa yang memengaruhi cara kita menilai berbagai implementasi pola desain. Mari kita mulai dengan yang baik. Berikut adalah faktor-faktor yang membuat implementasi lebih menarik dan menarik:
  • Inisialisasi malas: instance tidak dibuat sampai dibutuhkan.

  • Kode sederhana dan transparan: metrik ini, tentu saja, subjektif, tetapi penting.

  • Keamanan utas: operasi yang benar di lingkungan multi-utas.

  • Performa tinggi di lingkungan multi-utas: sedikit atau tidak ada pemblokiran utas saat berbagi sumber daya.

Sekarang kontra. Kami akan membuat daftar faktor-faktor yang membuat penerapan menjadi buruk:
  • Tidak ada inisialisasi malas: ketika kelas dimuat saat aplikasi dimulai, terlepas dari apakah itu diperlukan atau tidak (paradoksnya, di dunia IT lebih baik malas)

  • Kode yang rumit dan sulit dibaca. Metrik ini juga subjektif. Jika mata Anda mulai berdarah, kami menganggap penerapannya bukan yang terbaik.

  • Kurangnya keamanan benang. Dengan kata lain, "benang bahaya". Operasi yang salah di lingkungan multi-utas.

  • Performa buruk di lingkungan multi-utas: utas saling memblokir setiap saat atau sering saat berbagi sumber daya.

Kode

Sekarang kami siap untuk mempertimbangkan berbagai opsi implementasi dan menunjukkan pro dan kontra:

Sederhana


public class Singleton {
    private static final Singleton INSTANCE = new Singleton();
    
    private Singleton() {
    }
    
    public static Singleton getInstance() {
        return INSTANCE;
    }
}
Implementasi paling sederhana. Kelebihan:
  • Kode sederhana dan transparan

  • Keamanan benang

  • Performa tinggi di lingkungan multi-utas

Kontra:
  • Tidak ada inisialisasi malas.
Dalam upaya untuk memperbaiki kekurangan sebelumnya, kami mendapatkan implementasi nomor dua:

Inisialisasi malas


public class Singleton {
  private static final Singleton INSTANCE;

  private Singleton() {}

  public static Singleton getInstance() {
    if (INSTANCE == null) {
      INSTANCE = new Singleton();
    }
    return INSTANCE;
  }
}
Kelebihan:
  • Inisialisasi malas.

Kontra:
  • Tidak aman benang

Implementasi ini menarik. Kami dapat menginisialisasi dengan malas, tetapi kami kehilangan keamanan utas. Jangan khawatir — kami menyinkronkan semuanya dalam implementasi nomor tiga.

Akses tersinkronisasi


public class Singleton {
  private static final Singleton INSTANCE;

  private Singleton() {
  }

  public static synchronized Singleton getInstance() {
    if (INSTANCE == null) {
      INSTANCE = new Singleton();
    }
    return INSTANCE;
  }
}
Kelebihan:
  • Inisialisasi malas.

  • Keamanan benang

Kontra:
  • Performa multithread yang buruk

Bagus sekali! Dalam implementasi nomor tiga, kami memulihkan keamanan benang! Tentu saja lambat... Sekarang metode getInstance telah disinkronkan, sehingga hanya dapat dijalankan oleh satu utas dalam satu waktu. Daripada menyinkronkan seluruh metode, sebenarnya kita hanya perlu menyinkronkan bagian yang menginisialisasi instance baru. Tapi kita tidak bisa begitu saja menggunakan blok yang disinkronkan untuk membungkus bagian yang bertanggung jawab untuk membuat instance baru. Melakukan itu tidak akan memastikan keamanan benang. Semuanya sedikit lebih rumit. Sinkronisasi yang tepat dapat dilihat di bawah ini:

Penguncian diperiksa ulang


public class Singleton {
    private static final 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 di lingkungan multi-utas

Kontra:
  • Tidak didukung di versi Java sebelumnya di bawah 1.5 (penggunaan kata kunci volatil diperbaiki sejak versi 1.5)

Perhatikan bahwa agar opsi implementasi ini berfungsi dengan benar, salah satu dari dua syarat harus dipenuhi. Variabel INSTANCE harus berupa final atau volatile . Implementasi terakhir yang akan kita bahas hari ini adalah class holder singleton .

Pemegang kelas


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 di lingkungan multi-utas.

Kontra:
  • Operasi yang benar memerlukan jaminan bahwa objek tunggal diinisialisasi tanpa kesalahan. Jika tidak, panggilan pertama ke metode getInstance akan menghasilkan ExceptionInInitializerError , dan semua panggilan selanjutnya akan menghasilkan NoClassDefFoundError .

Implementasi ini hampir sempurna. Itu malas, dan benang aman, dan cepat. Tapi ada nuansanya, seperti yang dijelaskan di daftar kontra. Perbandingan berbagai implementasi pola singleton:
Penerapan Inisialisasi malas Keamanan benang Performa multithread Kapan harus digunakan?
Sederhana - + Cepat Tidak pernah. Atau mungkin saat inisialisasi malas tidak penting. Tapi tidak akan pernah lebih baik.
Inisialisasi malas + - Tak dapat diterapkan Selalu saat multithreading tidak diperlukan
Akses tersinkronisasi + + Lambat Tidak pernah. Atau mungkin saat kinerja multithreaded tidak menjadi masalah. Tapi tidak akan pernah lebih baik.
Penguncian diperiksa ulang + + Cepat Dalam kasus yang jarang terjadi ketika Anda perlu menangani pengecualian saat membuat singleton (ketika singleton pemegang kelas tidak berlaku)
Pemegang kelas + + Cepat Setiap kali multithreading diperlukan dan ada jaminan bahwa objek tunggal akan dibuat tanpa masalah.

Pro dan kontra dari pola singleton

Secara umum, singleton melakukan apa yang diharapkan darinya:
  1. Ini menjamin bahwa hanya akan ada satu instance kelas.

  2. Ini memberikan satu titik akses global ke instans itu.

Namun, pola ini memiliki kekurangan:
  1. Singleton melanggar prinsip tanggung jawab tunggal: selain tugas langsungnya, kelas singleton juga mengontrol jumlah instance.

  2. Ketergantungan kelas biasa pada singleton tidak terlihat dalam kontrak publik kelas.

  3. Variabel global buruk. Pada akhirnya, singleton berubah menjadi variabel global yang lumayan.

  4. Kehadiran singleton mengurangi testabilitas aplikasi secara keseluruhan dan kelas yang menggunakan singleton pada khususnya.

Dan itu saja! :) Kami telah menjelajahi Java Singleton Class bersama Anda. Sekarang, selama sisa hidup Anda, saat berbicara dengan teman programmer Anda, Anda tidak hanya dapat menyebutkan seberapa bagus polanya, tetapi juga beberapa kata tentang apa yang membuatnya buruk. Selamat menguasai ilmu baru ini.

Bacaan tambahan:

Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION