JavaRush /Blog Java /Random-MS /Corak Reka Bentuk: Singleton

Corak Reka Bentuk: Singleton

Diterbitkan dalam kumpulan
hello! Hari ini kita akan melihat dengan lebih dekat pada corak reka bentuk yang berbeza, dan kita akan bermula dengan corak Singleton, yang juga dipanggil "singleton". Corak Reka Bentuk: Singleton - 1Mari kita ingat: apa yang kita tahu tentang corak reka bentuk secara umum? Corak reka bentuk ialah amalan terbaik yang boleh diikuti untuk menyelesaikan beberapa masalah yang diketahui. Corak reka bentuk biasanya tidak terikat dengan mana-mana bahasa pengaturcaraan. Ambilnya sebagai satu set pengesyoran, berikutan itu anda boleh mengelakkan kesilapan dan tidak mencipta semula roda anda.

Apa itu singleton?

Singleton ialah salah satu corak reka bentuk paling mudah yang boleh digunakan pada kelas. Orang kadang-kadang berkata "kelas ini ialah singleton", bermakna kelas ini melaksanakan corak reka bentuk tunggal. Kadangkala perlu menulis kelas yang hanya satu objek boleh dibuat. Sebagai contoh, kelas yang bertanggungjawab untuk mengelog atau menyambung ke pangkalan data. Corak reka bentuk Singleton menerangkan bagaimana kita boleh mencapai tugas sedemikian. Singleton ialah corak reka bentuk yang melakukan dua perkara:
  1. Memberi jaminan bahawa kelas hanya akan mempunyai satu contoh kelas.

  2. Menyediakan pusat akses global kepada contoh kelas ini.

Oleh itu, terdapat dua ciri yang menjadi ciri hampir setiap pelaksanaan corak tunggal:
  1. Pembina persendirian. Mengehadkan keupayaan untuk mencipta objek kelas di luar kelas itu sendiri.

  2. Kaedah statik awam yang mengembalikan contoh kelas. Kaedah ini dipanggil getInstance. Ini ialah titik akses global kepada contoh kelas.

Pilihan pelaksanaan

Corak reka bentuk tunggal digunakan dengan cara yang berbeza. Setiap pilihan adalah baik dan buruk dengan caranya sendiri. Di sini, seperti biasa: tidak ada yang ideal, tetapi anda perlu berusaha untuk mendapatkannya. Tetapi pertama sekali, mari kita tentukan apa yang baik dan apa yang buruk, dan apakah metrik yang mempengaruhi penilaian pelaksanaan corak reka bentuk. Mari kita mulakan dengan yang positif. Berikut adalah kriteria yang memberikan kelazatan dan daya tarikan pelaksanaan:
  • Inisialisasi malas: apabila kelas dimuatkan semasa aplikasi berjalan tepat apabila ia diperlukan.

  • Kesederhanaan dan ketelusan kod: metrik, sudah tentu, adalah subjektif, tetapi penting.

  • Keselamatan benang: berfungsi dengan betul dalam persekitaran berbilang benang.

  • Prestasi tinggi dalam persekitaran berbilang benang: benang menyekat satu sama lain secara minimum atau tidak sama sekali apabila berkongsi sumber.

Sekarang keburukan. Kami menyenaraikan kriteria yang menunjukkan pelaksanaan dalam cahaya yang buruk:
  • Inisialisasi bukan malas: apabila kelas dimuatkan apabila aplikasi bermula, tidak kira sama ada ia diperlukan atau tidak (paradoks, dalam dunia IT adalah lebih baik untuk menjadi malas)

  • Kerumitan dan kebolehbacaan kod yang lemah. Metrik juga subjektif. Kita akan beranggapan jika darah datang dari mata, pelaksanaannya begitu-begitu sahaja.

  • Kekurangan keselamatan benang. Dalam erti kata lain, "bahaya benang". Operasi yang salah dalam persekitaran berbilang benang.

  • Prestasi buruk dalam persekitaran berbilang benang: benang menyekat satu sama lain sepanjang masa atau selalunya apabila berkongsi sumber.

Kod

Kini kami bersedia untuk mempertimbangkan pelbagai pilihan pelaksanaan, menyenaraikan kebaikan dan keburukan:

Penyelesaian Mudah

public class Singleton {
    private static final Singleton INSTANCE = new Singleton();

    private Singleton() {
    }

    public static Singleton getInstance() {
        return INSTANCE;
    }
}
Pelaksanaan paling mudah. Kelebihan:
  • Kesederhanaan dan ketelusan kod

  • Keselamatan benang

  • Prestasi tinggi dalam persekitaran berbilang benang

Kekurangan:
  • Bukan pemula malas.
Dalam usaha untuk membetulkan kecacatan terakhir, kami mendapat pelaksanaan nombor dua:

Permulaan 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.

Kekurangan:
  • Tidak selamat benang

Pelaksanaannya menarik. Kami boleh memulakan dengan malas, tetapi kami telah kehilangan keselamatan benang. Tiada masalah: dalam pelaksanaan nombor tiga kami menyegerakkan segala-galanya.

Aksesori Disegerakkan

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.

  • Keselamatan benang

Kekurangan:
  • Prestasi lemah dalam persekitaran berbilang benang

Hebat! Dalam pelaksanaan nombor tiga, kami membawa kembali keselamatan benang! Benar, ia perlahan... Kini kaedah itu getInstancedisegerakkan, dan anda hanya boleh memasukkannya satu demi satu. Sebenarnya, kita tidak perlu menyegerakkan keseluruhan kaedah, tetapi hanya sebahagian daripadanya di mana kita memulakan objek kelas baharu. Tetapi kita tidak boleh hanya membungkus synchronizedbahagian yang bertanggungjawab untuk mencipta objek baharu dalam blok: ini tidak akan memberikan keselamatan benang. Ia lebih rumit sedikit. Kaedah penyegerakan yang betul diberikan di bawah:

Penguncian Disemak Dua Kali

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.

  • Keselamatan benang

  • Prestasi tinggi dalam persekitaran berbilang benang

Kekurangan:
  • Tidak disokong pada versi Java yang lebih rendah daripada 1.5 (kata kunci yang tidak menentu telah ditetapkan dalam versi 1.5)

Saya perhatikan bahawa untuk pilihan pelaksanaan ini berfungsi dengan betul, satu daripada dua syarat diperlukan. Pembolehubah INSTANCEmestilah sama ada final, atau volatile. Pelaksanaan terakhir yang akan kita bincangkan hari ini ialah 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.

  • Keselamatan benang.

  • Prestasi tinggi dalam persekitaran berbilang benang.

Kekurangan:
  • Untuk operasi yang betul, adalah perlu untuk menjamin bahawa objek kelas Singletondimulakan tanpa ralat. Jika tidak, panggilan kaedah pertama getInstanceakan berakhir dengan ralat ExceptionInInitializerError, dan semua panggilan seterusnya akan gagal NoClassDefFoundError.

Pelaksanaannya hampir sempurna. Dan malas, dan selamat benang, dan pantas. Tetapi ada nuansa yang diterangkan dalam tolak. Jadual perbandingan pelbagai pelaksanaan corak Singleton:
Perlaksanaan Inisialisasi malas Keselamatan benang Kelajuan multithreading Bila nak guna?
Penyelesaian Mudah - + Cepat tidak pernah. Atau apabila permulaan malas tidak penting. Tetapi tidak pernah lebih baik.
Permulaan Malas + - Tidak berkaitan Sentiasa apabila multithreading tidak diperlukan
Aksesori Disegerakkan + + Perlahan-lahan tidak pernah. Atau apabila kelajuan kerja dengan multithreading tidak penting. Tetapi tidak pernah lebih baik
Penguncian Disemak Dua Kali + + Cepat Dalam kes yang jarang berlaku apabila anda perlu mengendalikan pengecualian semasa membuat singleton. (apabila Singleton Pemegang Kelas tidak berkenaan)
Pemegang Kelas Singleton + + Cepat Sentiasa apabila multithreading diperlukan dan terdapat jaminan bahawa objek kelas tunggal akan dicipta tanpa masalah.

Kebaikan dan keburukan corak Singleton

Secara umum, singleton melakukan apa yang diharapkan daripadanya:
  1. Memberi jaminan bahawa kelas hanya akan mempunyai satu contoh kelas.

  2. Menyediakan pusat akses global kepada contoh kelas ini.

Walau bagaimanapun, corak ini mempunyai kelemahan:
  1. Singleton melanggar SRP (Prinsip Tanggungjawab Tunggal) - kelas Singleton, sebagai tambahan kepada tanggungjawab segeranya, juga mengawal bilangan salinannya.

  2. Kebergantungan kelas biasa atau kaedah pada singleton tidak kelihatan dalam kontrak awam kelas.

  3. Pembolehubah global adalah buruk. Singleton akhirnya bertukar menjadi satu pembolehubah global yang besar.

  4. Kehadiran singleton mengurangkan kebolehujian aplikasi secara umum dan kelas yang menggunakan singleton khususnya.

OK semuanya sudah berakhir Sekarang. Kami melihat corak reka bentuk tunggal. Kini, dalam perbualan seumur hidup dengan rakan pengaturcara anda, anda akan dapat mengatakan bukan sahaja apa yang baik tentangnya, tetapi juga beberapa perkataan tentang apa yang buruk tentangnya. Semoga berjaya dalam menguasai ilmu baru.

Bacaan tambahan:

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