Ensure a class only has one instance, and provide a global point of access to it.
Използва се за случаите, в които искаме да гарантираме, че от даден клас ще имаме само един обект. Например при операции, които заемат повече памет, като обекти за работа с бази данни, файлове и т.н…
Също, може да се използва при нужда от т.н. lazy instantiation – отлагане създаването на обект, до момента в който вече наистина ни трябва.
Най-просто – правим инстанцирането „отвън“ (с new …) невъзможно като направим конструктора да е private. Също и клонирането с __clone() или десериализирането с __wakeup()
Инстанцирането ще става от обикновен публичен и статичен метод, например getInstance(), който ще ни е т.н. access point.
Декларираме си статична private променлива на класа, например $inst, в която ще съхраняваме обектът от класа.
И когато извикаме getInstance() за да ни върне обект, първо проверяваме дали вече имаме стойност в $inst, тоест обект, или е NULL и ако е NULL присвояваме и обект от класа със new self(); което пък ще извика private конструктора.
Ако има обект вече в $inst – връщаме го директно, без да правим нов.
Добре е да се знае, че при Singleton Pattern деструкторът на класа също се вика автоматично или при unset() както обикновено, и трябва да е public.
Aкo не е public ще имаме грешка Call to private SomeClass::__destruct() …
Singleton design pattern е доста проста и даден не-singleton клас може лесно да се преобразува в singleton такъв само с добавяне на метод за access point демек getInstance(), едно static private пропърти и да направим конструктора и __clone да са private.
Също, на не-singleton клас можем да направим наследника да е singleton.
Както и наследникът на singleton не е автоматично singleton.
Според мен, въпреки че Singleton DP е масово считан за antipattern и трябвало било да бъде избягван на всяка цена…, аз твърдя точно обратното – Singleton е един чудесен design pattern, но просто проблемът е, че е използван грешно. Toчно простотата му му изиграва лоша шега. Не може да използваш чук за да завиеш гайка, или отвертка – за да забиеш гвоздей, и да са ти виновни съответните инструменти. Виновен си ти като „майстор“, че ги използваш грешно.
Singleton създава един напълно пълнокръвен и обикновен обект, просто следи дали вече обект от този клас не съществува. Какво лошо има в това ако например създаването на този обект е „тежко“ и/или този обект е огромен, а във същото време неговите properties са непроменливи. Например – обект с различни config settings? Защо да не използваме Singleton?
Не е нужно да си „Айнщайн“ за да разбереш, че когато на Singleton обект му промениш на едно място някое/някои пропъртита, ще важи глобално… ми нали е един обект!
Не е нужно да си „Айнщайн“ за да разбереш, че е по-добре на инджектваш обект отвън, а не да инстанцираш вътре във функцията/методът, защото така нещата стават not-testable.
Явно тези грешки се допускат масово и от там разни „айнщайновци“ носят лошото име на Singleton DP, и тези „айнщайновци“ допускат такива грешки, точно защото Singleton DP е прост и лесен.
Литература:
https://www.codeproject.com/Articles/1178694/Singleton-and-Multiton-Pattern