Одинак (англ. Singleton) — шаблон проєктування, належить до класу твірних шаблонів. Гарантує, що клас матиме тільки один екземпляр, і забезпечує глобальну точку доступу до цього екземпляра.
Через низку притаманних недоліків деякі розробники вважають його антипатерном або «душком» коду.
Мотивація
Для деяких класів важливо, щоб існував тільки один екземпляр. Наприклад, хоча у системі може існувати декілька принтерів, може бути тільки один спулер. Повинна бути тільки одна файлова система та тільки один активний віконний менеджер.
Глобальна змінна не вирішує такої проблеми, бо не забороняє створити інші екземпляри класу.
Рішення полягає в тому, щоб сам клас контролював свою «унікальність», забороняючи створення нових екземплярів, та сам забезпечував єдину точку доступу. Це є призначенням шаблону Одинак.
Недоліки
Одинак в об'єктно-орієнтованому програмуванні можна порівняти з глобальною змінною у процедурному програмуванні з відповідними недоліками.
Зокрема, цей шаблон створює неявні залежності між функціями та методами, які не декларуються в їхньому інтерфейсі.
Крім того, Одинак може створювати проблеми під час модульного тестування адже, на додачу до всього іншого, його важко замінити на фіктивну реалізацію (англ. mock).
Ці та інші недоліки спонукали Еріха Гаму в інтерв'ю 2009 року визнати, що можливо він би відмовився від цього шаблону проєктування, адже вважає його використання одним із «душків» коду.
На думку Брайана Батона Одинак порушує один із принципів SOLID: принцип єдиної відповідальності, оскільки окрім власне бізнес логіки, на клас покладається відповідальність за виконання вимог до Одинака. Натомість, він пропонує виокремити функціональність Одинака в інший клас, наприклад, із використанням шаблону фабричного метода або абстрактної фабрики.
Деякі з перелічених вад можна позбутись застосуванням шаблону впровадження залежностей та принципу інверсії залежностей.
Застосування
Слід використовувати шаблон Одинак коли:
- повинен бути тільки один екземпляр деякого класу, що легко доступний всім клієнтам;
- єдиний екземпляр повинен розширюватись шляхом успадкування, та клієнтам потрібно мати можливість працювати з розширеним екземпляром не змінюючи свій код.
Структура
- Singleton — одинак:
- визначає операцію Instance, котра дозволяє клієнтам отримувати доступ до єдиного екземпляру. Instance — це операція класу;
- може нести відповідальність за створення власного унікального екземпляру.
Відносини
Клієнти отримують доступ до єдиного об'єкта класу Singleton лише через його операцію Instance.
Реалізації
Реалізації на
// Заголовний файл (.h) // // Ниттєбезпечна реалізація Одинака // // Ця версія виглядає оманливо просто, проте вона має застереження: // - Перше, якщо одинак міститься в якійсь бібліотеці. Ті, хто використовуватимуть цю бібліотеку // матимуть екземпляр одинака протягом роботи застосунка, незалежно // від того, чи використовується він чи ні. // // - Друге, це випадок статичних залежностей файлів. Наприклад, уявімо що // Singleton є якоюсь абстрактною фабрикою для типа BaseType, і // застосовується метод create. Оскільки порядок ініціалізації статичних змінних // протягом трансляції модулів не визначений, це може призвести // до доступу до Одинака до моменту його конструювання, іншими словами // до невизначеної поведінки, що є погана річ. // // namespace { const BaseType * const fileStaticVariable = Singleton::getInstance().create(); } // class Singleton { private: static Singleton _instance; Singleton() {} ~Singleton() {} Singleton(const Singleton &); Singleton & operator=(const Singleton &); public: static Singleton& getInstance(); }; // Джерельний файл (.cpp) // Ініціалізація статичного члена. Singleton Singleton::_instance; Singleton& Singleton::getInstance() { return _instance; }
Одинак Маєрса
Так званий «Одинак Маєрса» покладається на запроваджені у версії гарантії ниттєбезпечного ініціалізації статичної змінної в тілі методу. Таким чином, простий та ниттєбезпечний Одинак в реалізації Скота Маєрса (англ. Scott Meyers) виглядає так:
#ifndef SINGLETON_H_ #define SINGLETON_H_ class Singleton final { public: // Метод повертає посилання на єдиний екземпляр класу, який зберігається // в локальній статичній змінній static Singleton& getInstance() { // єдиний екземпляр цього класу зберігатиметься у локальній статичній змінній // на противагу попередньому прикладу, ініціалізація екземпляру гарантовано // відбудеться тільки під час першого виклику цього метода (ліниво). Тобто, // якщо цей метод ніколи не буде викликаний, то і екземпляр не буде створено static Singleton theInstance { }; return theInstance; } private: Singleton() = default; Singleton(const Singleton&) = delete; Singleton(Singleton&&) = delete; Singleton& operator=(const Singleton&) = delete; Singleton& operator=(Singleton&&) = delete; // ... }; #endif
Окрім нього, існують й інші варіанти шаблону Одинак без деяких його недоліків.
Реалізації на Java
Базовими засобами мови
Enum singleton, починаючи з Java 1.5:
public enum SingletonEnum { INSTANCE; }
Проста реалізація зі створенням об'єкта під час завантаження його класу
public class Singleton { private Singleton(){} private static final Singleton instance = new Singleton(); public static Singleton getInstance() { return instance; } }
Реалізація з відкладеним (ледачим) створенням об'єкта за потреби із синхронізацією для багатопоточної безпеки
public class Singleton { private Singleton(){} private static Singleton instance; public static synchronized Singleton getInstance() { if (instance==null) { instance = new Singleton(); } return instance; } }
Реалізація з відкладеним (ледачим) створенням об'єкта за потреби, яка є багатопоточно безпечною, використовується шаблон Initialization on demand holder. Проблемою реалізації є те, що коли виникає помилка з киданням винятку під час виконання статичної ініціалізації, клас не завантажується і екземпляр одинака більше неможливо створити.
public class Singleton { private Singleton() {} private static class SingletonHolder { private static final Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } }
Бібліотечними засобами
Якщо система розподілена, кожна JVM може мати свій екземпляр Одинака. У EJB 3.1 з'явилась анотація @Singleton, яка забезпечує унікальність Одинака на різних JVM
@Singleton public class SingletonA { }
За допомогою аспектів
Особливістю реалізації засобами мови програмування є необхідність для клієнта використовувати не конструктор, а фабричний метод для одержання об'єкта.
За допомогою засобів аспектно-орієнтованого програмування можна зробити реалізацію Одинака з використанням конструктора.
Реалізація за допомогою AspectJ
public abstract aspect AbstractSingletonAspect { private Object singleton = null; abstract pointcut singletonPointcut(); Object around(): singletonPointcut() { if (singleton == null) { singleton = proceed(); } return singleton; } } public aspect SingletonAspect extends AbstractSingletonAspect { pointcut singletonPointcut() : call(Stats.new(..)); }
Реалізація за допомогою . Код аспекта:
package aop.patterns.singleton; import org.jboss.aop.advice.Interceptor; import org.jboss.aop.joinpoint.Invocation; public class SingletonInterceptor implements Interceptor { private Object singleton; public Object invoke(Invocation invocation) throws Throwable { if (singleton==null) { singleton = invocation.invokeNext(); } return singleton; } }
Конфігурація у jboss-aop.xml
<bind pointcut="execution(aop.patterns.singleton.Singleton->new())"> <interceptor class="aop.patterns.singleton.SingletonInterceptor" /> </bind>
Реалізація на Actionscript 3.0
package { public class Singleton { private static var _instance:Singleton = new Singleton(); public function Singleton () { if (_instance){ throw new Error( "Singleton can only be accessed through Singleton.getInstance()" ); } } public static function getInstance():Singleton { return _instance; } } }
Реалізація на Ruby
Мова програмування Ruby має вбудовану підтримку деяких шаблонів, зокрема й Одинака.
Модуль Singleton з бібліотеки singleton робить конструктор приватним та надає фабричний метод.
require 'singleton' class MyClass include Singleton end a = MyClass.instance
Реалізація на Scala
У Scala шаблон підтримується засобами мови:
object Singleton // Використання: val singleton = Singleton
Реалізація на Smalltalk
Реалізація на Smalltalk :
new self error: 'cannot create new object' default SoleInstance isNil ifTrue: [SoleInstance := super new]. ^ SoleInstance
Реалізація на PHP5
Реалізація на PHP
<?php class Singleton { // object instance private static $instance; private function __construct() {} private function __clone() {} public static function getInstance() { if (self::$instance === null) { self::$instance = new self; } return self::$instance; } public function doAction() { ... } } //usage Singleton::getInstance()->doAction(); ?>
Реалізація на Delphi
Для Delphi 2005 та вище підходить наступний приклад:
type TSingleton = class strict private class var Instance: TSingleton; public class function NewInstance: TObject; override; end; class function TSingleton.NewInstance: TObject; begin if not Assigned(Instance) then Instance := TSingleton(inherited NewInstance); NewInstance := Instance; end;
Для більш ранніх версій треба перемістити код класу до окремого модулю, а оголошення Instance
замінити оголошенням глобальної змінної в його секції implementation
(до Delphi 7 включно секції class var
та strict private
були відсутніми).
Примітки
- Stephan Roth (2017). The Singleton Anti-Pattern. Clean C++. Apress. doi:10.1007/978-1-4842-2793-0. ISBN .
- Jim Hyslop, Herb Sutter (1 березня 2003). Once Is Not Enough. Dr. Dobbs Joural.
- Miško Hevery (17 серпня 2008). Singletons are Pathological Liars. Google Testing blog.
- Miško Hevery. . The Testability Explorer Blog. Архів оригіналу за 24 травня 2022. Процитовано 10 травня 2022.
- Michael C. Feathers (2005). The Case of the Irritating Global Dependency. Working Effectively with Legacy Code. Prentice Hall. ISBN .
- Klaus Iglberger (15 травня 2016). Thread-Safe Initialization of Data. Modernes CPP.
- Peter Muldoon (20 вересня 2020). Retiring the Singleton Pattern (PDF).
- Peter Haggar, IBM developerWorks: Double-checked locking and the Singleton pattern
- Singleton EJB
- Foundations of AOP for J2EE Development. Renaud Pawlak, Lionel Seinturier, and Jean-Philippe Retaillé. Apress 2005. .
- . Архів оригіналу за 13 травня 2007. Процитовано 8 травня 2007.
{{}}
: Обслуговування CS1: Сторінки з текстом «archived copy» як значення параметру title () - Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides. Addison-Wesley, 1994.
Див. також
Зовнішні посилання
- Singleton Pattern & its implementation with C++
- IBM developerWorks, Use your singletons wisely
- Singleton Pattern: A review and analysis of existing C++ implementations
Література
Алан Шаллоуей, Джеймс Р. Тротт. Шаблоны проектирования. Новый подход к объектно-ориентированному анализу и проектированию = Design Patterns Explained: A New Perspective on Object-Oriented Design. — М. : «Вильямс», 2002. — 288 с. — .
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
Odinak angl Singleton shablon proyektuvannya nalezhit do klasu tvirnih shabloniv Garantuye sho klas matime tilki odin ekzemplyar i zabezpechuye globalnu tochku dostupu do cogo ekzemplyara Cherez nizku pritamannih nedolikiv deyaki rozrobniki vvazhayut jogo antipaternom abo dushkom kodu MotivaciyaDlya deyakih klasiv vazhlivo shob isnuvav tilki odin ekzemplyar Napriklad hocha u sistemi mozhe isnuvati dekilka printeriv mozhe buti tilki odin spuler Povinna buti tilki odna fajlova sistema ta tilki odin aktivnij vikonnij menedzher Globalna zminna ne virishuye takoyi problemi bo ne zaboronyaye stvoriti inshi ekzemplyari klasu Rishennya polyagaye v tomu shob sam klas kontrolyuvav svoyu unikalnist zaboronyayuchi stvorennya novih ekzemplyariv ta sam zabezpechuvav yedinu tochku dostupu Ce ye priznachennyam shablonu Odinak NedolikiOdinak v ob yektno oriyentovanomu programuvanni mozhna porivnyati z globalnoyu zminnoyu u procedurnomu programuvanni z vidpovidnimi nedolikami Zokrema cej shablon stvoryuye neyavni zalezhnosti mizh funkciyami ta metodami yaki ne deklaruyutsya v yihnomu interfejsi Krim togo Odinak mozhe stvoryuvati problemi pid chas modulnogo testuvannya adzhe na dodachu do vsogo inshogo jogo vazhko zaminiti na fiktivnu realizaciyu angl mock Ci ta inshi nedoliki sponukali Eriha Gamu v interv yu 2009 roku viznati sho mozhlivo vin bi vidmovivsya vid cogo shablonu proyektuvannya adzhe vvazhaye jogo vikoristannya odnim iz dushkiv kodu Na dumku Brajana Batona Odinak porushuye odin iz principiv SOLID princip yedinoyi vidpovidalnosti oskilki okrim vlasne biznes logiki na klas pokladayetsya vidpovidalnist za vikonannya vimog do Odinaka Natomist vin proponuye viokremiti funkcionalnist Odinaka v inshij klas napriklad iz vikoristannyam shablonu fabrichnogo metoda abo abstraktnoyi fabriki Deyaki z perelichenih vad mozhna pozbutis zastosuvannyam shablonu vprovadzhennya zalezhnostej ta principu inversiyi zalezhnostej ZastosuvannyaSlid vikoristovuvati shablon Odinak koli povinen buti tilki odin ekzemplyar deyakogo klasu sho legko dostupnij vsim kliyentam yedinij ekzemplyar povinen rozshiryuvatis shlyahom uspadkuvannya ta kliyentam potribno mati mozhlivist pracyuvati z rozshirenim ekzemplyarom ne zminyuyuchi svij kod StrukturaDiagrama klasiv sho opisuye strukturu shablonu proyektuvannya OdinakSingleton odinak viznachaye operaciyu Instance kotra dozvolyaye kliyentam otrimuvati dostup do yedinogo ekzemplyaru Instance ce operaciya klasu mozhe nesti vidpovidalnist za stvorennya vlasnogo unikalnogo ekzemplyaru VidnosiniKliyenti otrimuyut dostup do yedinogo ob yekta klasu Singleton lishe cherez jogo operaciyu Instance RealizaciyiRealizaciyi na C Zagolovnij fajl h Nittyebezpechna realizaciya Odinaka Cya versiya viglyadaye omanlivo prosto prote vona maye zasterezhennya Pershe yaksho odinak mistitsya v yakijs biblioteci Ti hto vikoristovuvatimut cyu biblioteku matimut ekzemplyar odinaka protyagom roboti zastosunka nezalezhno vid togo chi vikoristovuyetsya vin chi ni Druge ce vipadok statichnih zalezhnostej fajliv Napriklad uyavimo sho Singleton ye yakoyus abstraktnoyu fabrikoyu dlya tipa BaseType i zastosovuyetsya metod create Oskilki poryadok inicializaciyi statichnih zminnih protyagom translyaciyi moduliv ne viznachenij ce mozhe prizvesti do dostupu do Odinaka do momentu jogo konstruyuvannya inshimi slovami do neviznachenoyi povedinki sho ye pogana rich namespace const BaseType const fileStaticVariable Singleton getInstance create class Singleton private static Singleton instance Singleton Singleton Singleton const Singleton amp Singleton amp operator const Singleton amp public static Singleton amp getInstance Dzherelnij fajl cpp Inicializaciya statichnogo chlena Singleton Singleton instance Singleton amp Singleton getInstance return instance Odinak Mayersa Tak zvanij Odinak Mayersa pokladayetsya na zaprovadzheni u versiyi C 11 garantiyi nittyebezpechnogo inicializaciyi statichnoyi zminnoyi v tili metodu Takim chinom prostij ta nittyebezpechnij Odinak v realizaciyi Skota Mayersa angl Scott Meyers viglyadaye tak ifndef SINGLETON H define SINGLETON H class Singleton final public Metod povertaye posilannya na yedinij ekzemplyar klasu yakij zberigayetsya v lokalnij statichnij zminnij static Singleton amp getInstance yedinij ekzemplyar cogo klasu zberigatimetsya u lokalnij statichnij zminnij na protivagu poperednomu prikladu inicializaciya ekzemplyaru garantovano vidbudetsya tilki pid chas pershogo vikliku cogo metoda linivo Tobto yaksho cej metod nikoli ne bude viklikanij to i ekzemplyar ne bude stvoreno static Singleton theInstance return theInstance private Singleton default Singleton const Singleton amp delete Singleton Singleton amp amp delete Singleton amp operator const Singleton amp delete Singleton amp operator Singleton amp amp delete endif Okrim nogo isnuyut j inshi varianti shablonu Odinak bez deyakih jogo nedolikiv Realizaciyi na Java Bazovimi zasobami movi Enum singleton pochinayuchi z Java 1 5 public enum SingletonEnum INSTANCE Prosta realizaciya zi stvorennyam ob yekta pid chas zavantazhennya jogo klasu public class Singleton private Singleton private static final Singleton instance new Singleton public static Singleton getInstance return instance Realizaciya z vidkladenim ledachim stvorennyam ob yekta za potrebi iz sinhronizaciyeyu dlya bagatopotochnoyi bezpeki public class Singleton private Singleton private static Singleton instance public static synchronized Singleton getInstance if instance null instance new Singleton return instance Realizaciya z vidkladenim ledachim stvorennyam ob yekta za potrebi yaka ye bagatopotochno bezpechnoyu vikoristovuyetsya shablon Initialization on demand holder Problemoyu realizaciyi ye te sho koli vinikaye pomilka z kidannyam vinyatku pid chas vikonannya statichnoyi inicializaciyi klas ne zavantazhuyetsya i ekzemplyar odinaka bilshe nemozhlivo stvoriti public class Singleton private Singleton private static class SingletonHolder private static final Singleton instance new Singleton public static Singleton getInstance return SingletonHolder instance Bibliotechnimi zasobami Yaksho sistema rozpodilena kozhna JVM mozhe mati svij ekzemplyar Odinaka U EJB 3 1 z yavilas anotaciya Singleton yaka zabezpechuye unikalnist Odinaka na riznih JVM Singleton public class SingletonA Za dopomogoyu aspektiv Osoblivistyu realizaciyi zasobami movi programuvannya ye neobhidnist dlya kliyenta vikoristovuvati ne konstruktor a fabrichnij metod dlya oderzhannya ob yekta Za dopomogoyu zasobiv aspektno oriyentovanogo programuvannya mozhna zrobiti realizaciyu Odinaka z vikoristannyam konstruktora Realizaciya za dopomogoyu AspectJ public abstract aspect AbstractSingletonAspect private Object singleton null abstract pointcut singletonPointcut Object around singletonPointcut if singleton null singleton proceed return singleton public aspect SingletonAspect extends AbstractSingletonAspect pointcut singletonPointcut call Stats new Realizaciya za dopomogoyu Kod aspekta package aop patterns singleton import org jboss aop advice Interceptor import org jboss aop joinpoint Invocation public class SingletonInterceptor implements Interceptor private Object singleton public Object invoke Invocation invocation throws Throwable if singleton null singleton invocation invokeNext return singleton Konfiguraciya u jboss aop xml lt bind pointcut execution aop patterns singleton Singleton amp gt new gt lt interceptor class aop patterns singleton SingletonInterceptor gt lt bind gt Realizaciya na Actionscript 3 0 package public class Singleton private static var instance Singleton new Singleton public function Singleton if instance throw new Error Singleton can only be accessed through Singleton getInstance public static function getInstance Singleton return instance Realizaciya na Ruby Mova programuvannya Ruby maye vbudovanu pidtrimku deyakih shabloniv zokrema j Odinaka Modul Singleton z biblioteki singleton robit konstruktor privatnim ta nadaye fabrichnij metod require singleton class MyClass include Singleton end a MyClass instance Realizaciya na Scala U Scala shablon pidtrimuyetsya zasobami movi object Singleton Vikoristannya val singleton Singleton Realizaciya na Smalltalk Realizaciya na Smalltalk new self error cannot create new object default SoleInstance isNil ifTrue SoleInstance super new SoleInstance Realizaciya na PHP5 Realizaciya na PHP lt php class Singleton object instance private static instance private function construct private function clone public static function getInstance if self instance null self instance new self return self instance public function doAction usage Singleton getInstance gt doAction gt Realizaciya na Delphi Dlya Delphi 2005 ta vishe pidhodit nastupnij priklad type TSingleton class strict private class var Instance TSingleton public class function NewInstance TObject override end class function TSingleton NewInstance TObject begin if not Assigned Instance then Instance TSingleton inherited NewInstance NewInstance Instance end Dlya bilsh rannih versij treba peremistiti kod klasu do okremogo modulyu a ogoloshennya Instance zaminiti ogoloshennyam globalnoyi zminnoyi v jogo sekciyi implementation do Delphi 7 vklyuchno sekciyi class var ta strict private buli vidsutnimi PrimitkiStephan Roth 2017 The Singleton Anti Pattern Clean C Apress doi 10 1007 978 1 4842 2793 0 ISBN 978 1 4842 2792 3 Jim Hyslop Herb Sutter 1 bereznya 2003 Once Is Not Enough Dr Dobbs Joural Misko Hevery 17 serpnya 2008 Singletons are Pathological Liars Google Testing blog Misko Hevery The Testability Explorer Blog Arhiv originalu za 24 travnya 2022 Procitovano 10 travnya 2022 Michael C Feathers 2005 The Case of the Irritating Global Dependency Working Effectively with Legacy Code Prentice Hall ISBN 0 13 117705 2 Button Brian 25 travnya 2004 Being Scott Densmore Microsoft Arhiv originalu za 15 lipnya 2021 Procitovano 28 serpnya 2021 Klaus Iglberger 15 travnya 2016 Thread Safe Initialization of Data Modernes CPP Peter Muldoon 20 veresnya 2020 Retiring the Singleton Pattern PDF Peter Haggar IBM developerWorks Double checked locking and the Singleton pattern Singleton EJB Foundations of AOP for J2EE Development Renaud Pawlak Lionel Seinturier and Jean Philippe Retaille Apress 2005 ISBN 1 59059 507 6 Arhiv originalu za 13 travnya 2007 Procitovano 8 travnya 2007 a href wiki D0 A8 D0 B0 D0 B1 D0 BB D0 BE D0 BD Cite web title Shablon Cite web cite web a Obslugovuvannya CS1 Storinki z tekstom archived copy yak znachennya parametru title posilannya Design Patterns Elements of Reusable Object Oriented Software by Erich Gamma Richard Helm Ralph Johnson John Vlissides Addison Wesley 1994 ISBN 0 201 63361 2Div takozhTvirni shabloni Multiton shablon proyektuvannya Zovnishni posilannyaSingleton Pattern amp its implementation with C IBM developerWorks Use your singletons wisely Singleton Pattern A review and analysis of existing C implementationsLiteraturaAlan Shallouej Dzhejms R Trott Shablony proektirovaniya Novyj podhod k obektno orientirovannomu analizu i proektirovaniyu Design Patterns Explained A New Perspective on Object Oriented Design M Vilyams 2002 288 s ISBN 0 201 71594 5