Yaqinda biz bilan Singleton nima ekanligini, uni Java'da qanday amalga oshirish va nima uchun kerakligini ko'rib chiqdik. Lekin agar men senga aytsam, Java'da allaqachon o'zining qutilari ichidagi singletoni mavjud? Qiziqmi? Unda boshladik.
Aftidan, sen allaqachon enum klassi haqida bilasan. Unga o'ziga xos xususiyat mavjud, bilish kerak bo'lgan. Gap shundaki, enum singletonning bir ko'rinishidir. Bu variant deyarli public maydonli usulga o'xshaydi.
Singleton as enum:
public enum Device {
PRINTER
}
Public variable singleton:
public class Printer {
public static final Printer PRINTER = new Printer();
private Printer() {
}
//…
}
Public maydonli variantda enum bilan ishlash yanada ixchamroq — o'zining realizatsiyasini yozish kerak emas. Va eng muhimi — enumlar serializatsiya bilan muammo yashamaydi.
Bu yerda serializatsiya oddiy obyektlarga nisbatan boshqacha ishlaydi: enumning faqat nom qiymati serializatsiya qilinadi. Deserializatsiya paytida usul deserializatsiya qilingan nom bilan ishlatiladi, shunda nusxa olinadi. Bundan tashqari, enum o'zini refleksiv hujumlardan himoya qilishga imkon beradi.
| Reflection haqida ko'proq ikkinchi modul darslaridan, Reflection API mavzusida bilib olasan. |
Java enumlarning instantsiyalanishiga taqiq qo'yadi va bu newInstance metodi Constructor klassi, ko'pincha refleksiyada ob'ektlar yaratishda chaqiriladigan, amalga oshiriladi.
Constructor.newInstance dan enum yaratish kodi mexanizmi:
if ((clazz.getModifiers() & Modifier.ENUM) != 0)
throw new IllegalArgumentException("Cannot reflectively create enum objects");
Enum orqali Singleton yaratishda kamchiliklar:
Keçikib ishga tushirish yo'qligi, chunki obyekt darhol yaratiladi va kechiktirilgan ishga tushirish qilinmaydi.
Boshqa klasslarni kengaytirish imkonsizligi. Ya'ni, boshqa klassdan meros olish kerak bo'lgan hollarda enumni Singleton sifatida ishlatish mumkin emas. Bunday hollarda bizga tanish bo'lgan statik metod yoki public maydon orqali realizatsiya qilish usullariga murojaat qilish kerak.
Enumni singleton sifatida ishlatib, faqat bir maydonni enum klassida ishlatishing mumkin.
public enum Device extends Electricity {
PRINTER
}
Bunday kod kompilatsiya xatosini chiqaradi:
Agar bizga interfeysni amalga oshirish kerak bo'lsa, hech qanday muammo yo'q: enum interfeyslarni amalga oshirishi mumkin:
public enum Device implements Electricity {
PRINTER
}
Agar meros olishni ishlatishga ehtiyoj bo'lmasa, Singletonni enum orqali amalga oshirish yaxshiroq. Bu nafaqat bizning, balki Joshuy Blochning tavsiyasi.
Bunday realizatsiyani ishlatish senga qulaylik, kompaktlik, qutilardagi serializatsiya, refleksiv hujumlardan himoya va yagona bo'lish imkoniyatini beradi, bu esa yaxshi Singleton uchun kerakdir!
GO TO FULL VERSION