JavaRush /Java блогы /Random-KK /Дизайн үлгілері: Singleton

Дизайн үлгілері: Singleton

Топта жарияланған
Сәлеметсіз бе! Бүгін біз әртүрлі дизайн үлгілерін егжей-тегжейлі қарастырамыз және біз Singleton үлгісінен бастаймыз, ол «синглтон» деп те аталады. Дизайн үлгілері: Singleton - 1Еске түсірейік: жалпы дизайн үлгілері туралы не білеміз? Дизайн үлгілері - бірқатар белгілі мәселелерді шешу үшін ұстануға болатын ең жақсы тәжірибелер. Дизайн үлгілері әдетте ешқандай бағдарламалау тіліне байланысты емес. Оларды ұсыныстар жиынтығы ретінде қабылдаңыз, содан кейін сіз қателіктерден аулақ бола аласыз және дөңгелегін қайта ойлап таппайсыз.

Синглтон дегеніміз не?

Синглтон - сыныпқа қолдануға болатын қарапайым дизайн үлгілерінің бірі. Адамдар кейде «бұл класс синглтон» деп айтады, яғни бұл класс синглондық дизайн үлгісін жүзеге асырады. Кейде тек бір an object құруға болатын класс жазу қажет. Мысалы, журналға немесе дерекқорға қосылуға жауапты сынып. Singleton дизайн үлгісі мұндай тапсырманы қалай орындауға болатынын сипаттайды. Синглтон - бұл екі нәрсені жасайтын дизайн үлгісі:
  1. Сыныпта сыныптың тек бір данасы болатынына кепілдік береді.

  2. Осы сыныптың данасына жаһандық кіру нүктесін береді.

Демек, синглтон үлгісінің әрбір дерлік орындалуына тән екі ерекшелік бар:
  1. Жеке конструктор. Сыныптың өзінен тыс сынып нысандарын жасау мүмкіндігін шектейді.

  2. Сынып данасын қайтаратын жалпыға ортақ статикалық әдіс. Бұл әдіс деп аталады getInstance. Бұл сынып данасына жаһандық кіру нүктесі.

Іске асыру нұсқалары

Синглтон дизайн үлгісі әртүрлі тәсілдермен қолданылады. Әрбір нұсқа өзінше жақсы және жаман. Мұнда, әдеттегідей: идеал жоқ, бірақ оған ұмтылу керек. Бірақ, ең алдымен, ненің жақсы, ненің жаман екенін және дизайн үлгісін жүзеге асыруды бағалауға қандай көрсеткіштер әсер ететінін анықтайық. Позитивтен бастайық. Міне, іске асырудың шырындылығы мен тартымдылығын беретін критерийлер:
  • Жалқау инициализация: қолданба дәл қажет болғанда жұмыс істеп тұрған кезде сынып жүктелгенде.

  • Кодтың қарапайымдылығы мен ашықтығы: метрика, әрине, субъективті, бірақ маңызды.

  • Жіп қауіпсіздігі: көп ағынды ортада дұрыс жұмыс істейді.

  • Көп ағынды ортада жоғары өнімділік: ағындар ресурсты ортақ пайдалану кезінде бір-бірін аздап блоктайды немесе мүлдем блоктайды.

Енді кемшіліктер. Іске асыруды нашар көрсететін критерийлерді тізіп көрейік:
  • Жалқау емес инициализация: қажет немесе қажет еместігіне қарамастан, қолданба іске қосылғанда сынып жүктелгенде (парадокс, IT әлемінде жалқау болған дұрыс)

  • Кодтың күрделілігі және нашар оқылуы. Көрсеткіш те субъективті. Көзден қан шықса, іске асуы солай деп есептейміз.

  • Жіп қауіпсіздігінің болмауы. Басқаша айтқанда, «жіп қаупі». Көп ағынды ортада дұрыс емес әрекет.

  • Көп ағынды ортада нашар өнімділік: ағындар бір-бірін үнемі немесе ресурсты ортақ пайдалану кезінде жиі блоктайды.

Код

Енді біз оң және теріс жақтарын тізіп, әртүрлі енгізу нұсқаларын қарастыруға дайынбыз:

Қарапайым шешім

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

    private Singleton() {
    }

    public static Singleton getInstance() {
        return INSTANCE;
    }
}
Ең қарапайым іске асыру. Артықшылықтары:
  • Кодтың қарапайымдылығы мен ашықтығы

  • Жіп қауіпсіздігі

  • Көп ағынды ортада жоғары өнімділік

Минустары:
  • Жалқау инициализация емес.
Соңғы кемшілікті түзету әрекеті үшін біз екінші орындалуды аламыз:

Жалқау инициализация

public class Singleton {
  private static Singleton INSTANCE;

  private Singleton() {}

  public static Singleton getInstance() {
    if (INSTANCE == null) {
      INSTANCE = new Singleton();
    }
    return INSTANCE;
  }
}
Артықшылықтары:
  • Жалқау инициализация.

Минустары:
  • Жіп қауіпсіз емес

Іске асыру қызықты. Біз жалқаулықпен инициализациялай аламыз, бірақ біз жіп қауіпсіздігін жоғалттық. Мәселе жоқ: үшінші орындалуда біз барлығын синхрондаймыз.

Синхрондалған аксессуар

public class Singleton {
  private static Singleton INSTANCE;

  private Singleton() {
  }

  public static synchronized Singleton getInstance() {
    if (INSTANCE == null) {
      INSTANCE = new Singleton();
    }
    return INSTANCE;
  }
}
Артықшылықтары:
  • Жалқау инициализация.

  • Жіп қауіпсіздігі

Минустары:
  • Көп ағынды ортада нашар өнімділік

Тамаша! Үшінші орындалуда біз жіп қауіпсіздігін қайтардық! Рас, бұл баяу... Енді әдіс getInstanceсинхрондалған және оны бір-бірден енгізуге болады. Шындығында, бізге бүкіл әдісті синхрондау қажет емес, тек оның жаңа класс нысанын инициализациялайтын бөлігі ғана. synchronizedБірақ біз блокта жаңа нысанды жасауға жауапты бөлікті жай ғана орау мүмкін емес : бұл жіп қауіпсіздігін қамтамасыз етпейді. Бұл сәл күрделірек. Дұрыс синхрондау әдісі төменде келтірілген:

Екі рет тексерілген құлыптау

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;
    }
}
Артықшылықтары:
  • Жалқау инициализация.

  • Жіп қауіпсіздігі

  • Көп ағынды ортада жоғары өнімділік

Минустары:
  • 1.5-тен төмен Java нұсқаларында қолдау көрсетілмейді (ұшпа кілт сөз 1.5 нұсқасында бекітілді)

Бұл іске асыру опциясының дұрыс жұмыс істеуі үшін екі шарттың бірі қажет екенін ескертемін. Айнымалы не , немесе INSTANCEболуы керек . Біз бүгін талқылайтын соңғы іске асыру болып табылады . finalvolatileClass Holder 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;
   }
}
Артықшылықтары:
  • Жалқау инициализация.

  • Жіп қауіпсіздігі.

  • Көп ағынды ортада жоғары өнімділік.

Минустары:
  • SingletonДұрыс жұмыс істеу үшін сынып an objectісі қатесіз инициализацияланғанына кепілдік беру қажет . Әйтпесе, бірінші әдісті шақыру getInstanceқатемен аяқталады ExceptionInInitializerError, ал кейінгілерінің барлығы сәтсіз болады NoClassDefFoundError.

Іске асыру мінсіз дерлік. Және жалқау, жіпсіз және жылдам. Бірақ минуста сипатталған нюанс бар. Singleton үлгісінің әртүрлі іске асыруларының салыстыру кестесі:
Іске асыру Жалқау инициализация Жіп қауіпсіздігі Көп ағынды жылдамдық Қашан пайдалану керек?
Қарапайым шешім - + Жылдам Ешқашан. Немесе жалқау инициализация маңызды болмаған кезде. Бірақ ешқашан жақсы емес.
Жалқау инициализация + - Жатпайды Әрқашан көп ағынды қажет етпейтін кезде
Синхрондалған аксессуар + + Баяу Ешқашан. Немесе көп ағынмен жұмыс жылдамдығы маңызды емес кезде. Бірақ ешқашан жақсы емес
Екі рет тексерілген құлыптау + + Жылдам Сирек жағдайларда, синглтонды жасау кезінде ерекше жағдайларды өңдеу қажет. (Class Holder Singleton қолданылмаған кезде)
Сынып ұстаушы синглтон + + Жылдам Әрқашан көп ағынды қажет болғанда және синглтон класының нысаны еш қиындықсыз жасалатынына кепілдік бар.

Синглтон үлгісінің жақсы және жаман жақтары

Жалпы, синглтон одан күткен нәрсені жасайды:
  1. Сыныпта сыныптың тек бір данасы болатынына кепілдік береді.

  2. Осы сыныптың данасына жаһандық кіру нүктесін береді.

Дегенмен, бұл үлгінің кемшіліктері бар:
  1. Singleton SRP (Single Responsibility Principle) бұзады - Singleton класы өзінің тікелей міндеттерінен басқа, оның көшірмелерінің санын да бақылайды.

  2. Тұрақты сыныптың немесе әдістің синглтонға тәуелділігі сыныптың жалпы келісімінде көрінбейді.

  3. Жаһандық айнымалылар нашар. Синглтон ақырында бір үлкен жаһандық айнымалыға айналады.

  4. Синглонның болуы жалпы қолданбаның және синглтонды пайдаланатын сыныптардың тексерілу мүмкіндігін төмендетеді.

Сонымен бітті. Біз синглтон дизайн үлгісін қарадық. Енді бағдарламашы достарыңызбен өмір бойы әңгімеде сіз оның жақсы жағын ғана емес, оның ненің жаман екенін де айта аласыз. Жаңа білімді меңгеруде сәттілік.

Қосымша оқу:

Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION