JavaRush /Java Blogu /Random-AZ /Dizayn nümunələri: Singleton

Dizayn nümunələri: Singleton

Qrupda dərc edilmişdir
Salam! Bu gün biz müxtəlif dizayn nümunələrini daha yaxından nəzərdən keçirəcəyik və “singleton” da adlandırılan Singleton naxışından başlayacağıq. Dizayn nümunələri: Singleton - 1Xatırlayaq: ümumiyyətlə dizayn nümunələri haqqında nə bilirik? Dizayn nümunələri bir sıra məlum problemləri həll etmək üçün izlənilə bilən ən yaxşı təcrübələrdir. Dizayn nümunələri ümumiyyətlə heç bir proqramlaşdırma dili ilə əlaqəli deyil. Onları tövsiyələr toplusu kimi qəbul edin, sonra səhvlərdən qaça və təkərinizi yenidən ixtira etməyəsiniz.

Singleton nədir?

Singleton bir sinifə tətbiq oluna bilən ən sadə dizayn nümunələrindən biridir. İnsanlar bəzən “bu sinif singletondur” deyirlər, yəni bu sinif singleton dizayn modelini həyata keçirir. Bəzən yalnız bir obyekt yaradıla bilən bir sinif yazmaq lazımdır. Məsələn, verilənlər bazasına daxil olmaq və ya qoşulmaq üçün məsul olan sinif. Singleton dizayn nümunəsi belə bir tapşırığı necə yerinə yetirə biləcəyimizi təsvir edir. Singleton iki şeyi yerinə yetirən dizayn nümunəsidir:
  1. Sinfin yalnız bir nümunəsinə sahib olacağına zəmanət verir.

  2. Bu sinfin nümunəsinə qlobal giriş nöqtəsi təqdim edir.

Beləliklə, singleton modelinin demək olar ki, hər bir tətbiqi üçün xarakterik olan iki xüsusiyyət var:
  1. Şəxsi konstruktor. Sinfin özündən kənarda sinif obyektləri yaratmaq imkanını məhdudlaşdırır.

  2. Sinfin nümunəsini qaytaran ictimai statik metod. Bu üsul deyilir getInstance. Bu, sinif nümunəsinə qlobal giriş nöqtəsidir.

İcra variantları

Singilton dizayn nümunəsi müxtəlif yollarla istifadə olunur. Hər bir seçim öz yolunda yaxşı və pisdir. Burada, həmişə olduğu kimi: ideal yoxdur, amma bunun üçün səy göstərmək lazımdır. Ancaq hər şeydən əvvəl, nəyin yaxşı və nəyin pis olduğunu və dizayn nümunəsinin həyata keçirilməsinin qiymətləndirilməsinə hansı ölçülərin təsir etdiyini müəyyən edək. Müsbətdən başlayaq. Tətbiqə şirəlilik və cəlbedicilik verən meyarlar bunlardır:
  • Tənbəl başlatma: proqram tam olaraq lazım olduqda işləyərkən sinif yükləndikdə.

  • Kodun sadəliyi və şəffaflığı: metrik, əlbəttə ki, subyektivdir, lakin vacibdir.

  • Mövzu təhlükəsizliyi: çox yivli mühitdə düzgün işləyir.

  • Çox yivli mühitdə yüksək performans: resurs paylaşarkən iplər bir-birini minimal şəkildə bloklayır və ya heç blok etmir.

İndi mənfi cəhətləri. Həyata keçirilməsini pis şəkildə göstərən meyarları sadalayaq:
  • Tənbəl olmayan başlatma: ehtiyac olub-olmamasından asılı olmayaraq, proqram işə salındıqda sinif yükləndikdə (paradoks, İT dünyasında tənbəl olmaq daha yaxşıdır)

  • Kodun mürəkkəbliyi və zəif oxunması. Metrik də subyektivdir. Güman edəcəyik ki, gözdən qan gəlirsə, icrası belədir.

  • İp təhlükəsizliyinin olmaması. Başqa sözlə, "yiv təhlükəsi". Çox yivli mühitdə səhv əməliyyat.

  • Çox yivli mühitdə zəif performans: resurs paylaşarkən mövzular hər zaman və ya tez-tez bir-birini bloklayır.

Kod

İndi müsbət və mənfi cəhətləri sadalayan müxtəlif tətbiq variantlarını nəzərdən keçirməyə hazırıq:

Sadə Həll

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

    private Singleton() {
    }

    public static Singleton getInstance() {
        return INSTANCE;
    }
}
Ən sadə icra. Müsbət cəhətləri:
  • Kodun sadəliyi və şəffaflığı

  • İp təhlükəsizliyi

  • Çox yivli mühitdə yüksək performans

Minuslar:
  • Tənbəl başlatma deyil.
Son qüsuru düzəltmək cəhdi olaraq, iki nömrəli tətbiq alırıq:

Lazy Initialization

public class Singleton {
  private static Singleton INSTANCE;

  private Singleton() {}

  public static Singleton getInstance() {
    if (INSTANCE == null) {
      INSTANCE = new Singleton();
    }
    return INSTANCE;
  }
}
Müsbət cəhətləri:
  • Tənbəl başlatma.

Minuslar:
  • İplik təhlükəsiz deyil

İcrası maraqlıdır. Biz tənbəlliklə işə sala bilərik, lakin mövzu təhlükəsizliyini itirmişik. Problem yoxdur: üçüncü proqramda biz hər şeyi sinxronlaşdırırıq.

Sinxronlaşdırılmış Aksessuar

public class Singleton {
  private static Singleton INSTANCE;

  private Singleton() {
  }

  public static synchronized Singleton getInstance() {
    if (INSTANCE == null) {
      INSTANCE = new Singleton();
    }
    return INSTANCE;
  }
}
Müsbət cəhətləri:
  • Tənbəl başlatma.

  • İp təhlükəsizliyi

Minuslar:
  • Çox yivli mühitdə zəif performans

Əla! Üçüncü tətbiqdə biz iplik təhlükəsizliyini geri qaytardıq! Doğrudur, yavaşdır ... İndi üsul getInstancesinxronlaşdırılıb və siz onu yalnız bir-bir daxil edə bilərsiniz. Əslində, bütün metodu sinxronizasiya etmək lazım deyil, yalnız onun yeni sinif obyektini işə saldığımız hissəsidir. synchronizedAmma biz sadəcə olaraq yeni obyektin yaradılmasına cavabdeh olan hissəni bloka bağlaya bilmərik : bu, ipin təhlükəsizliyini təmin etməyəcək. Bir az daha mürəkkəbdir. Düzgün sinxronizasiya üsulu aşağıda verilmişdir:

İkiqat yoxlanılmış kilidləmə

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;
    }
}
Müsbət cəhətləri:
  • Tənbəl başlatma.

  • İp təhlükəsizliyi

  • Çox yivli mühitdə yüksək performans

Minuslar:
  • 1.5-dən aşağı Java versiyalarında dəstəklənmir (uçucu açar söz 1.5 versiyasında düzəldilib)

Qeyd edirəm ki, bu tətbiq variantının düzgün işləməsi üçün iki şərtdən biri tələb olunur. Dəyişən ya , ya da INSTANCEolmalıdır . Bu gün müzakirə edəcəyimiz son tətbiq . finalvolatileClass Holder Singleton

Sinif Sahibi 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;
   }
}
Müsbət cəhətləri:
  • Tənbəl başlatma.

  • İp təhlükəsizliyi.

  • Çox yivli mühitdə yüksək performans.

Minuslar:
  • SingletonDüzgün işləmək üçün sinif obyektinin səhvsiz işə salınmasına zəmanət vermək lazımdır . Əks halda, birinci metod çağırışı getInstancexəta ilə başa çatacaq ExceptionInInitializerErrorvə bütün sonrakılar uğursuz olacaq NoClassDefFoundError.

Tətbiq demək olar ki, mükəmməldir. Və tənbəl, ipdən təhlükəsiz və sürətli. Ancaq minusda təsvir olunan bir nüans var. Singleton modelinin müxtəlif tətbiqlərinin müqayisə cədvəli:
İcra Tənbəl başlatma İp təhlükəsizliyi Çox iş parçacığı sürəti Nə vaxt istifadə etməli?
Sadə Həll - + Sürətli Heç vaxt. Və ya tənbəl başlatma vacib olmadıqda. Amma heç vaxt daha yaxşı.
Lazy Initialization + - Uyğun deyil Həmişə multithreading lazım olmadıqda
Sinxronlaşdırılmış Aksessuar + + Yavaş-yavaş Heç vaxt. Və ya multithreading ilə iş sürəti fərq etmədikdə. Amma heç vaxt daha yaxşı deyil
İkiqat yoxlanılmış kilidləmə + + Sürətli Nadir hallarda, təkton yaratarkən istisnaları idarə etmək lazım olduqda. (Class Holder Singleton tətbiq edilmədikdə)
Sinif Sahibi Singleton + + Sürətli Həmişə multithreading tələb olunduqda və singleton sinif obyektinin problemsiz yaradılacağına zəmanət olduqda.

Singleton modelinin müsbət və mənfi cəhətləri

Ümumiyyətlə, singleton ondan gözlənilən şeyi edir:
  1. Sinfin yalnız bir nümunəsinə sahib olacağına zəmanət verir.

  2. Bu sinfin nümunəsinə qlobal giriş nöqtəsi təqdim edir.

Bununla birlikdə, bu modelin mənfi cəhətləri var:
  1. Singleton SRP-ni (Single Responsibility Principle) pozur - Singleton sinfi bilavasitə məsuliyyətlərinə əlavə olaraq, nüsxələrinin sayına da nəzarət edir.

  2. Adi sinif və ya metodun singletondan asılılığı sinfin açıq müqaviləsində görünmür.

  3. Qlobal dəyişənlər pisdir. Singilton nəticədə bir böyük qlobal dəyişənə çevrilir.

  4. Singiltonun mövcudluğu ümumiyyətlə tətbiqin və xüsusilə singletondan istifadə edən siniflərin sınaqdan keçirilməsini azaldır.

Tamam, indi hər şey bitdi. Biz singleton dizayn nümunəsinə baxdıq. İndi proqramçı dostlarınızla ömürlük söhbətdə siz nəinki yaxşı olduğunu, həm də onun nəyin pis olduğunu bir neçə kəlmə söyləyə biləcəksiniz. Yeni biliklərə yiyələnməkdə uğurlar.

Əlavə oxu:

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION