Что такое синглтон: Singleton (Одиночка) или статический класс? / Хабр
Реализация Singleton в JAVA / Хабр
В этой статье я хочу затронуть тему одного из наиболее распространенных паттернов объектно-ориентированного программирования – Singleton. Но в данном случае я не буду описывать преимущества/недостатки и области применения этого паттерна, а попытаюсь изложить свой взгляд на его имплементацию в JAVA.
Общие сведения
Паттерн Singleton гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа.
Область применения
1.) В системе должно существовать не более одного экземпляра заданного класса.
2.) Экземпляр должен быть легко доступен для всех клиентов данного класса.
3.) Создание объекта on demand, то есть, когда он понадобится первый раз, а не во время инициализации системы.
Реализация (JAVA):
На данный момент существуют несколько вариантов реализации со своими недостатками и преимуществами. В них мы и попробуем сейчас разобраться.
Вариант первый – самый простой, который приходит в голову сразу после понимания проблемы.
У этого решения есть единственный недостаток – оно не работает в многопоточной среде и поэтому не подходит в большинстве случаев. Решение подходит исключительно для однопоточных приложений.
Не беда, скажите вы, и предложите следующее решение.
Вариант второй:
И вы будете правы, так как проблему многопоточности мы решили, но потеряли две важные вещи:
1. Ленивую инициализацию (Объект instance будет создан classloader-ом во время инициализации класса)
2. Отсутствует возможность обработки исключительных ситуаций(exceptions) во время вызова конструктора.
Решение подходит для многопоточных приложений, при условии отсутствия опасности возникновения исключительных ситуаций в конструкторе и отсутствии необходимости ленивой инициализации.
Далее возникают 2 варианта решения.
1.) Использование внутреннего класса(решение Била Пью(Bill Pugh) “Initialization on Demand Holder”).
2.) Использование синхронизации.
Начнем с Била Пью.
Вариант третий:
“Initialization on Demand Holder”
В данном случае мы полностью решили проблему ленивой инициализации – объект инициализируется при первом вызове метода getInstance(). Но у нас осталась проблема с обработкой исключительных ситуаций в конструкторе. Так что, если конструктор класса не вызывает опасений создания исключительных ситуаций, то смело можно использовать этот метод.
Синхронизация
Этой части я хотел бы уделить особое внимание. Можно было бы подойти к данному вопросу с заголовком «synchronized – мифы и реальность».
И так, самый прямолинейный метод.
Вариант четвертый:
У этого варианта есть только один недостаток. Синхронизация полезна только один раз, при первом обращении к getInstance(), после этого каждый раз, при обращении этому методу, синхронизация просто забирает время. Что можно сказать по этому поводу? Ну, во-первых, если вызов getInstance() не происходит достаточно часто (что значит «достаточно часто» решать вам), то этот метод имеет преимущество перед остальными – прост, понятен, лениво инициализируется, дает возможность обрабатывать исключительные ситуации в конструкторе. А во-вторых, синхронизация в Java перестала быть обременительно медленной настолько, насколько ее боятся. Ну что еще для счастья надо?
Теперь рассмотрим вариант синхронизированного решения, в котором попытаемся решить проблему, возникшую в предыдущем варианте.
Наиболее распространенный способ — «Double-Checked Locking». В своем оригинальном варианте:
Не работает! Почему? Это отдельная тема, но для интересующихся могу посоветовать прочитать эту статью http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html.
Но не надо совсем отчаиваться, в JAVA 5 проблему решили, используя модификатор volatile. На данный момент решение выглядит так:
Вариант пятый:
Не смотря на то, что этот вариант выглядит как идеальное решение, использовать его не рекомендуется т.к. товарищ Allen Holub заметил, что использование volatile модификатора может привести к проблемам производительности на мультипроцессорных системах. Но решать все же вам.
Вот, в общем-то, и все распространенные варианты имплементаций данного паттерна. Но, на этом не заканчиваются подводные камни Singleton-а. Существуют еще несколько моментов, которые нужно учитывать во время проектирования того или иного приложения, использующего Singleton.
Подводные камни
1. Наследование
В подавляющем большинстве случаев в Singleton классах наследование не нужно и, более того, излишне и является следствием over-design. Да и реализация наследования имеет определенные сложности, учитывая, что и сам instance и метод getInstance() статические.
Поэтому, я рекомендую использовать модификатор final и запретить наследование данного класса, если нет особой необходимости в обратном.
2. Две и более виртуальных машины
Каждая виртуальная машина создает свою копию Singleton объекта. И хотя на первый взгляд это выглядит очевидным, во многих распределенных системах, таких как EJB, JINI и RMI все не так просто. Когда промежуточные уровни скрывают (делают прозрачными) распределенные технологи, бывает трудно сказать, где и когда инициализирован объект.
3.Различные Class Loader-ы
Когда 2 class loader-а загружают класс, каждый из них может создать свою копию Singleton-а(в тех случаях, когда instance инициализируется class loader-ом ). Это особенно актуально в использовании сервлетов(servlet), так как в некоторых имплементациях серверов приложений(application server) каждый сервлет имеет свой class loader.
Существует еще ряд проблем, которые менее актуальны (такие как технология reflection и имплементация интерфейсов Cloneable и Serializable), и не будут мною рассмотрены в силу своей экзотичности в сфере применения Singleton классов. Но, в любом случае, с радостью отвечу на любые вопросы к этому материалу.
Вот, в общем-то, и все ключевые моменты, которые я хотел осветить в данной статье. Осталось лишь заметить, что данный материал не претендует быть истиной в последней инстанции и допускает существование точек зрения, отличающихся от точки зрения автора. И даже более того, любые замечания приветствуются и будут прияты к сведению.
Спасибо за внимание.
Для чего нужен singleton? — Хабр Q&A
В буквальном смысле синглтон призван упростить владение, инициализацию, контроль времени жизни и доступ к элементам глобального состояния программы. Эта фраза является самой важной. А важнее всего — правильно понять ее.
Подход многократно обличался антипаттерном за то, что «глобальное состояние программы — это зло», не смотря на то, что глобальное состояние продолжает оставаться в программе не смотря на удаление всех синглтонов из проекта.
Я видел проекты с более чем 50 синглтонами и очень тяжелыми проблемами их связи между собой. В синглтоны без разбора и по незнанке вытаскивали буквально все. Это яркий пример антиподхода применения абсолютно любого паттерна.
Важно понимать что никакой элемент проектирования не является антипаттерном, он приводит к проблемам только при неумелом использовании.
Приложение состоящее ровно из одной UI формы будет иметь глобальное состояние в виде этой формы вне зависимости от того, будет ли эта форма оформлена как синглтон или нет. Просто, если нет, то этой формой приходится управлять иными путями, не всегда более удобными чем синглтон.
В качестве альтернативы синглтонам пропагандируются два других подхода: Registry / Service locator и Dependency injection.
К слову, все альтернативы столь же активно и все так же незаслуженно обзываются антипаттернами. 🙂
Теперь к примерам.
— DirectX. Для работы с графикой тебе необходимо по одной инстанции интерфейсов IDirect3D и IDirect3DDevice. Эти две инстанции декларируют глобальное состояние программы. Инстанции всех буферов, текстур, шейдеров и поверхностей создаются с использованием этих инстанций. Разумным будет предоставить доступ к инстанциям DirectX через подход синглтона.
— OpenGL старых добрых версий. Процедурный интерфейс OpenGL как бы намекает на отсутствие необходимости в глобальном состоянии. Но не тут то было. Для работы с OpenGL необходимо не просто создать контекст, но еще и помнить поток, в котором этот контекст связан с поверхностью вывода. В многопоточной среде контекстов может быть несколько для параллельной загрузки ресурсов. В этом случае помнить надо уже два потока и два контекста (минимум). Само собой, в синглтоне это глобальное состояние смотрится удобнее.
— Sockets. Не важно какие. Когда твое приложение представляет собой MMO проект и у тебя гора подсистем, постоянно и обособленно общающихся с сервером, сетевое подключение разумно оформить в виде синглтона.
— Assets/Resources — они бывают разные, кешируемые и нет, доступные из сети, с жесткого диска, из подсистемы пререндеринга. Опять же, я несколько раз видел боль и страдания от неоднородного контроля ресурсов без соответствующей подсистемы. А сама подсистема управления ресурсами всегда централизована и лучше всего реализуется именно на синглтоне.
Звук, ввод, многопоточный конвеер задач… вспоминать места явной необходимости синглтонов можно еще долго.
«Я — синглтон». Почему людям для счастья больше не нужны отношения — Нож
В прошлом
Значительные изменения в понимании феномена одиночества произошли в начале ХХ столетия, когда мужчины и женщины без пары: молодые профессионалы, представители богемы и интеллигенции, геи и феминистки — устремились в большие города. Целые районы, такие как Гринвич-Виллидж в Нью-Йорке, Сохо в Лондоне и Монпарнас в Париже, стали заселять инакомыслящие одиночки — и именно здесь рождались самые передовые идеи того времени.
В крупных городах России дух перемен, воспетый русскими авангардистами, и социальные последствия революции привели к пертурбациям в семейной сфере. Традиционное супружество вытесняет новая форма внебрачных отношений — сожительство, увеличивается число разводов, процветает свободная любовь. Остро стоит квартирный вопрос, люди ютятся в коммуналках — иметь семью теперь экономически невыгодно.
Ровно век спустя мы снова становимся свидетелями социальных процессов, способствующих переоценке «преимуществ» семейной жизни, всегда считавшихся очевидными. В ближайшие годы женатые люди могут оказаться в меньшинстве — пришло время одиночек.
Статистика
«В наши дни одинокими являются более 50 % взрослых американцев; 31 млн человек… проживают в одиночестве.
<…>
…[В] Швеции, Дании, Норвегии и Финляндии — стран[ах], имеющих один из самых высоких уровней жизни… около 40 % домохозяйств состоит всего из одного человека.
<…>
…Во всём мире число людей, проживающих в одиночестве, резко увеличилось — со 153 млн в 1996 году до 201 млн в 2006 году, то есть за 10 лет количество таких людей возросло на 33 %».
По результатам последней переписи населения, в России 40 % населения имеют статус одиноких — никогда не состояли в браке (зарегистрированном или так называемом гражданском), вдовствуют или разведены. При этом, согласно данным опроса ВЦИОМ, 79 % россиян вовсе не чувствуют себя одиноко, а 54 % опрошенных отсутствие пары не пугает.
Современные одиночки
The Guy — Чувак — безымянный герой сериала High Maintenance, который третий сезон выходит на остросоциальном канале НВО, — пример современного одиночки, или «синглтона». Впервые это понятие использовал в 2012 году социолог, доктор философии Нью-Йоркского университета Эрик Кляйненберг.
Синглтоны — жители больших городов, которые непрочным семейным связям и сомнительным отношениям предпочитают одиночество.
Чувак, как и многие другие мужчины и женщины его поколения, ведет насыщенную социальную жизнь, успешен в своем деле, очевидно нравится людям — и у него нет пары.
Создатель сериала и исполнитель главной роли Бен Синклер говорит в интервью: «Вначале мы хотели, чтобы он чувствовал себя одиноко, а потом подумали: эй, а что, если с ним всё нормально?» Многочисленные исследования жизни синглтонов подтверждают: так оно и есть.
«В наши дни молодые одиночки, — пишет Кляйненберг, — стремятся активно „переформатировать“ представление о том, что их существование является показателем социального фиаско, в прямо противоположное — что оно свидетельствует о неординарности личности и об успехе. <…> Инвестиции в себя необходимы потому, что современные семьи часто распадаются, работа не является стабильной, и в конечном счете каждый из нас может надеяться только на самого себя».
«Я вполне гармонично ощущаю себя в статусе одинокого человека и не понимаю людей, которые всеми силами пытаются его изменить. Если появляется подходящий человек — это другое дело. А до тех пор нужно наслаждаться жизнью и как можно круче раскрывать себя, а потом будет что и в детей вложить».
Наташа, 33 года, градостроительница
Сегодня всё реже используются такие эпитеты, как «холостяк», «старая дева», «разведенка». Очевидно, что семейный статус мужчины никак не сказывается на его способности к зачатию. Зато отцы, оказавшиеся в этой роли без особого желания, плохо с ней справляющиеся или вовсе ее отвергающие, склонны страдать от чувства вины и рискуют вызвать резкое осуждение в обществе.
«Многие считают, что я просто боюсь брать на себя ответственность за женщину и ребенка — оттого и не завожу семью. Но пока я не вполне понимаю, для чего мне это нужно. У меня остаются сомнения, что благодаря таким изменениям моя жизнь станет лучше. А идти на это из-за предрассудков о „правильной жизни“ и „мужском долге“ я, конечно, не буду!»
Евгений, 42 года, архитектор
В стране, где более половины браков заканчиваются разводами, пренебрежительное отношение к одиночкам и вовсе нелепо и становится моветоном. Тем не менее такие люди продолжают испытывать на себе социальное давление. Доктор философии Белла Депауло, которая сама всю жизнь обходится без пары, в своей книге говорит о дискриминации одиноких людей и даже вводит особый термин — «синглизм» (по аналогии с «расизмом» и «сексизмом»).
Проявлений синглизма множество — от упущений в законодательных актах до привычной пренебрежительной манеры общения с неженатыми людьми.
«Мама переживает по поводу моего одиночества. Да, это на меня влияет. Иногда я начинаю загоняться, хотя и понимаю, что зря».
Наталья, 37 лет, режиссер
Депауло утверждает: уровень счастья у семейных людей лишь немного выше, чем у одиноких, а по прошествии некоторого времени он снова достигает прежней отметки. Замужние женщины в той же мере подвержены стрессу, депрессии, так же часто чувствуют себя «покинутыми», как и те, что живут без «второй половинки»: «Одинокие люди не заслуживают пренебрежительного отношения к себе и дискриминации, такое поведение обусловлено стереотипами».
Главный страх
«Страшнее смерти может быть только смерть в одиночестве» — опрос показывает, что подобные идеи больше не актуальны. 65 % жителей Москвы и Санкт-Петербурга уверены, что не стали бы сохранять фактически распавшийся брак из-за боязни одинокой старости.
По утверждению Кляйненберга, острее всего одиночество переживают люди, которые недавно овдовели, особенно если после ухода супруга/супруги резко возрастает риск болезни, смерти или маячит пугающая перспектива переезда в дом престарелых.
По статистике, большинство пар в России распадается после 5–9 лет совместной жизни. Тех, кто подает на развод после 20 лет брака, тоже немало — 13 %. Выходит, сохранить отношения до самой смерти удается совсем немногим.
А что, если супруг, на которого возложена почетная миссия провожатого в мир иной, отправится туда раньше? Или, оказавшись на годы прикованным к постели, сам будет нуждаться в постоянном уходе? К тому же не каждому захочется в случае смертельного заболевания полностью зависеть от другого.
«Я привыкла сама о себе заботиться. Мысль о том, что в старости я стану для кого-то обузой, меня ужасает. Лучше я заранее побеспокоюсь о сиделке или месте в доме престарелых, чем позволю мужчине взять на себя эту роль».
Инга, 29 лет, издательница
Жизнь без секса хуже смерти
«Больше всего меня пугает отсутствие секса. Что такие периоды будут затягиваться. Но по своему опыту я знаю: не заниматься сексом, когда ты одна, не так мучительно, как когда ты живешь в браке, но секса всё равно нет».
Соня, 35 лет, писательница
По словам Кляйненберга, «жизнь в одиночестве дает несколько преимуществ: сексуальную свободу и пространство, где можно экспериментировать с этой свободой, возможность развиваться, расти и искать настоящую любовь». В то же время приведенные ученым статистические данные, как и результаты других исследований, свидетельствуют, что в жизни синглтонов бывают долгие периоды воздержания:
«Мужчины среднего возраста, снова вступившие в брак, имеют больше шансов жить половой жизнью, чем те, кто развелся, но остался один. 57 % мужчин, проживающих с партнером… заявили, что занимались сексом раз в неделю или больше… по сравнению с 43 % мужчин, проживающих без партнера. <…> Одинокие мужчины мастурбируют в два раза чаще…
Для женщин сексуальных преимуществ в браке еще больше.
[Из тех, кто снова вступил в брак или стал жить с партнером] 54% [занимаются] сексом раз или более в неделю. [Тогда как среди разведенных женщин сексуально удовлетворенных было только 9 %]. Ответы женщин на вопрос о том, живут ли они в целибате, рисуют картину отчаяния: 17 % вновь вышедших замуж и 77 % разведенных и незамужних женщин заявили, что [вообще не ведут половой жизни]».
«В первое время после расставания отсутствие тактильных ощущений причиняет мне сильное физическое страдание. Кажется, я просто не выживу: как же так — не обниматься, спать одному? Постепенно боль затихает и ущерб от отсутствия контакта перестает быть разрушительным. Я как будто частично засыпаю, а остальные функции работают нормально».
Евгений, 42 года, архитектор
У одинокого человека, которого удручает отсутствие секса, есть масса возможностей изменить ситуацию — в то время как люди, связанные семейными узами, лишены такой привилегии.
Исследование, ставившее целью определить степень интегрированности одиночек в общественную жизнь, подтверждает: синглтоны имеют больше контактов с родственниками, соседями и друзьями, чем те, кто состоит в браке. «Есть все основания утверждать, что живущие в одиночестве люди компенсируют свое состояние повышенной социальной активностью, превышающей активность тех, кто проживает совместно, а в городах, где много одиночек, бурлит культурная жизнь».
В большом городе
«Становясь всё более популярным, этот феномен изменяет „социальную ткань“ и представление о человеческих взаимоотношениях, влияет на особенности градостроительства и развития экономики», — продолжает Кляйненберг. И далее: «Большинство живущих в одиночестве — не бедные, а, напротив, финансово независимые люди».
Быть синглтоном выгодно экономически. Человек располагает большим количеством времени, которое может потратить в том числе на работу, что при должном усердии обеспечит рост доходов.
К тому же когда ты один, то сам несешь ответственность за свои расходы.
Коворкинги, коливинги, новые форматы публичных библиотек, рестораны с общими столами, сидеть за которыми психологически комфортнее, чем за стандартными «на двоих», — жизнь одиночек становится всё более приспособленной под их «специфические» нужды.
Синглтоны — настоящие гейм-чейнджеры на рынке недвижимости. По словам управляющего бюро FlatForma Сергея Хмелёва, Москва продолжает перестраиваться под влиянием нового поколения резидентов. Застройщики разрабатывают и внедряют форматы квартир не только для семей с детьми, но также для пар и одиночек. В некоторых жилых комплексах предлагаются апартаменты площадью от 14 м2 — для тех, кто приходит домой, чтобы переночевать.
Свойственное одиночкам стремление к комфорту и бережное отношение к личным границам помогают им более эффективно организовывать свою жизнь.
«У меня был идеальный формат отношений: у нее есть свой дом, у меня — свой. Мы жили в одном округе Москвы, дорога занимала 20 минут. Мне очень нравилось бывать у нее, я всегда мог позвать ее к себе или остаться дома один».
Евгений, 42 года, архитектор
Одни, но не одиноки
Мы постоянно окружены людьми. Нас учат думать, что сами мы не способны сделать себя счастливыми, что для этого нам обязательно нужен кто-то еще.
«В состояние одиночества нужно погрузиться, осознать его, прочувствовать. Поначалу оно может вызывать дискомфорт и даже страдание, но, прислушавшись к себе, вы обнаружите, что на самом деле так намного приятнее, чем находиться рядом с неподходящим человеком».
Соня, 35 лет, писательница
Многие из тех, кто когда-либо жили в одиночестве, подтвердят: нет состояния более естественного и гармоничного, если принимать его сознательно, не обращая внимания на общественное мнение или навязчивую социальную политику государства.
«Я единственный ребенок в семье. У меня всегда была своя комната, я привыкла с детства быть одна. Это состояние для меня естественно. Был период, когда я снимала квартиры с другими людьми, — интересный опыт и в целом фан. Но когда у меня снова появилось свое жилье, я вздохнула с облегчением».
Наталья, 37 лет, режиссер
Спокойное отношение к одиночеству позволяет нам адекватнее оценить наши социальные связи и сделать выбор в пользу тех людей, находиться с которыми нам так же комфортно, как с самими собой.
Если же общение происходит по инерции, если нами движут социальные установки или нерациональные страхи — может, стоить дать себе время подумать? В одиночестве.
Одиночка
Также известен как: Singleton
Суть паттерна
Одиночка — это порождающий паттерн проектирования, который гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа.
Проблема
Одиночка решает сразу две проблемы, нарушая принцип единственной ответственности класса.
Гарантирует наличие единственного экземпляра класса. Чаще всего это полезно для доступа к какому-то общему ресурсу, например, базе данных.
Представьте, что вы создали объект, а через некоторое время пробуете создать ещё один. В этом случае хотелось бы получить старый объект, вместо создания нового.
Такое поведение невозможно реализовать с помощью обычного конструктора, так как конструктор класса всегда возвращает новый объект.
Клиенты могут не подозревать, что работают с одним и тем же объектом.
Предоставляет глобальную точку доступа. Это не просто глобальная переменная, через которую можно достучаться к определённому объекту. Глобальные переменные не защищены от записи, поэтому любой код может подменять их значения без вашего ведома.
Но есть и другой нюанс. Неплохо бы хранить в одном месте и код, который решает проблему №1, а также иметь к нему простой и доступный интерфейс.
Интересно, что в наше время паттерн стал настолько известен, что теперь люди называют «одиночками» даже те классы, которые решают лишь одну из проблем, перечисленных выше.
Решение
Все реализации одиночки сводятся к тому, чтобы скрыть конструктор по умолчанию и создать публичный статический метод, который и будет контролировать жизненный цикл объекта-одиночки.
Если у вас есть доступ к классу одиночки, значит, будет доступ и к этому статическому методу. Из какой точки кода вы бы его ни вызвали, он всегда будет отдавать один и тот же объект.
Аналогия из жизни
Правительство государства — хороший пример одиночки. В государстве может быть только одно официальное правительство. Вне зависимости от того, кто конкретно заседает в правительстве, оно имеет глобальную точку доступа «Правительство страны N».
Структура
Одиночка определяет статический метод
getInstance
, который возвращает единственный экземпляр своего класса.Конструктор одиночки должен быть скрыт от клиентов. Вызов метода
getInstance
должен стать единственным способом получить объект этого класса.
Псевдокод
В этом примере роль Одиночки отыгрывает класс подключения к базе данных.
Этот класс не имеет публичного конструктора, поэтому единственный способ получить его объект — это вызвать метод getInstance
. Этот метод сохранит первый созданный объект и будет возвращать его при всех последующих вызовах.
// Класс одиночки определяет статический метод `getInstance`,
// который позволяет клиентам повторно использовать одно и то же
// подключение к базе данных по всей программе.
class Database is
// Поле для хранения объекта-одиночки должно быть объявлено
// статичным.
private static field instance: Database
// Конструктор одиночки всегда должен оставаться приватным,
// чтобы клиенты не могли самостоятельно создавать
// экземпляры этого класса через оператор `new`.
private constructor Database() is
// Здесь может жить код инициализации подключения к
// серверу баз данных.
// ...
// Основной статический метод одиночки служит альтернативой
// конструктору и является точкой доступа к экземпляру этого
// класса.
public static method getInstance() is
if (Database.instance == null) then
acquireThreadLock() and then
// На всякий случай ещё раз проверим, не был ли
// объект создан другим потоком, пока текущий
// ждал освобождения блокировки.
if (Database.instance == null) then
Database.instance = new Database()
return Database.instance
// Наконец, любой класс одиночки должен иметь какую-то
// полезную функциональность, которую клиенты будут
// запускать через полученный объект одиночки.
public method query(sql) is
// Все запросы к базе данных будут проходить через эт
Singleton — это… Что такое Singleton?
- Singleton
Одиночка, (англ. Singleton) — порождающий шаблон проектирования.
Цель
Гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа. Существенно то, что можно пользоваться именно экземпляром класса, так как при этом во многих случаях становится доступной более широкая функциональность. Например, к описанным компонентам класса можно обращаться через интерфейс, если такая возможность поддерживается языком.
Плюсы
- контролируемый доступ к единственному экземпляру;
- уменьшение числа имён;
- допускает уточнение операций и представления;
- допускает переменное число экземпляров;
- большая гибкость, чем у операций класса.
Минусы
- Глобальные объекты могут быть вредны для объектного программирования, в некоторых случаях приводя к созданию немасштабируемого проекта.
Применение
- должен быть ровно один экземпляр некоторого класса, легко доступный всем клиентам;
- единственный экземпляр должен расширяться путем порождения подклассов, и клиентам нужно иметь возможность работать с расширенным экземпляром без модификации своего кода
Пример реализации
Пример Java 1.5
class Singleton { private volatile static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
Пример Java 1.5: Class holder on JVM start initialization
public class Singleton { protected Singleton() {} private static class SingletonHolder { public static Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } }
Пример Java 1.5: Enum singleton
public class SingletonEnum { INSTANCE; public void someMethod() { *** } public void anotherMethod() { *** } }
Пример Python
>>> class Singleton(object): obj = None # Атрибут для хранения единственного экземпляра def __new__(cls,*dt,**mp): # класса Singleton. if cls.obj is None: # Если он еще не создан, то cls.obj = object.__new__(cls,*dt,**mp) # вызовем __new__ родительского класса return cls.obj # вернем синглтон ... >>> obj = Singleton() >>> obj.attr = 12 >>> new_obj = Singleton() >>> new_obj.attr 12 >>> new_obj is obj # new_obj и obj - это один и тот же объект True
Пример C++
Возможная реализация на C++ (известная как синглтон Мейерса), где одиночка представляет собой статический локальный объект (важно: это решение не потоко-безопасно и приводится только для того, чтобы показать как устроен шаблон, а не для реального использования в крупномасштабных программных проектах. Кроме того, данная реализация не обеспечивает невозможность создать еще один экземпляр класса).
template<typename T> class Singleton { public: static T& Instance() { static T theSingleInstance; // у класса T есть конструктор по умолчанию return theSingleInstance; } }; class OnlyOne : public Singleton<OnlyOne> { //.. интерфейс класса };
Пример C#
/// generic Singleton<T> (потокобезопасный с использованием generic-класса и с отложенной инициализацией) /// <typeparam name="T">Singleton class</typeparam> public class Singleton<T> where T : class, new() { /// Защищенный конструктор по умолчанию необходим для того, чтобы /// предотвратить создание экземпляра класса Singleton protected Singleton() { } /// Фабрика используется для отложенной инициализации экземпляра класса private sealed class SingletonCreator<S> where S : class, new() { private static readonly S instance = new S(); public static S CreatorInstance { get { return instance; } } } public static T Instance { get { return SingletonCreator<T>.CreatorInstance; } } } /// Использование Singleton public class TestClass : Singleton<TestClass> { public string TestProc() { return "Hello World"; } }
Так же можно использовать стандартный вариант потокобезопасной реализации Singleton с отложенной инициализацией:
public class Singleton { protected Singleton() { } private sealed class SingletonCreator { private static readonly Singleton instance = new Singleton(); public static Singleton Instance { get { return instance; } } } public static Singleton Instance { get { return SingletonCreator.Instance; } } }
Пример PHP 4
<?php class Singleton { function Singleton( $directCall = true ) { if ( $directCall ) { trigger_error("Нельзя использовать конструктор для создания класса Singleton. Используйте статический метод getInstance ()",E_USER_ERROR); } //TODO: Добавьте основной код конструктора здесь } function &getInstance() { static $instance; if ( !is_object( $instance ) ) { $instance = new Singleton( false ); } return $instance; } } ?>
Пример PHP 5
<?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
unit Unit1; interface type TSingleton = class strict private constructor Create; class var FInstance: TSingleton; public class function GetInstance: TSingleton; end; implementation constructor TSingleton.Create; begin inherited; end; class function TSingleton.GetInstance: TSingleton; begin if FInstance = nil then begin FInstance := TSingleton.Create(); end; Result := FInstance; end; end.
Пример на языке
Singleton := Object clone Singleton clone := Singleton
Пример на языке
class Singleton
def self.new
@instance ||= super
end
end
В стандартную библиотеку (Ruby 1.8 и выше) входит модуль Singleton, что позволяет создавать синглтоны еще проще:
require 'singleton' class Foo include Singleton end a = Foo.instance # Foo.new недоступен, для получения ссылки на (единственный) # экземпляр класса Foo следует использовать метод Foo#instance
Пример на Common Lisp
(defclass singleton-class () ;;метакласс, реализующий механизм синглтона ((instance :initform nil))) (defmethod validate-superclass ((class singleton-class) (superclass standard-class)) t) ;;Разрешаем наследование классов-синглтонов от обычных классов (defmethod validate-superclass ((class singleton-class) (superclass singleton-class)) t) ;;Разрешаем наследование классов-синглтонов от других классов-синглтонов (defmethod validate-superclass ((class standard-class) (superclass singleton-class)) nil) ;;Запрещаем наследование обычных классов от синглтонов (defmethod make-instance ((class singleton-class) &key) (with-slots (instance) class (or instance (setf instance (call-next-method))))) (defclass my-singleton-class () () (:metaclass singleton-class))
Пример на
package Singleton;
use strict;
my $singleton;
sub new {
my $class = shift();
return $singleton ||= bless(sub {1}, $class);
}
1;
Реализация шаблона Singleton в Python
Шаблон Singleton (Одиночка) один из самых часто используемых шаблонов. Его можно встретить во множестве проектов и он относительно прост для обучения. Его обязательно нужно знать и уметь его использовать.
Статья написана на основе книги: Python: Master the Art of Design Patterns (Dusty Phillips, Chetan Giridhar, Sakis Kasampalis)
В этой статье будет кратко рассмотрены следующие темы:
• Как устроен Singleton
• Реальный пример паттерна Singleton
• Реализация шаблона Singleton в Python
• Шаблон Monostate
Как устроен Singleton
Шаблон Singleton предоставляет механизм создания одного и только один экземпляра объекта, и предоставление к нему глобальную точку доступа. Поэтому, Singletons обычно используются в таких случаях, как ведение журнала или операции с базой данных, диспетчера очереди печати и многих других, где существует необходимость иметь только один экземпляр, который доступен во всем приложении, чтобы избежать конфликтующих запросов на один и тот же ресурс. Например, мы можем захотеть использовать один объект базы данных для выполнения операций с БД для обеспечения согласованности данных или один объект класса ведения журнала для нескольких служб, чтобы последовательно выгружать сообщения журнала в определенный файл журнала.
Вкратце, цель шаблона Singleton заключаются в следующем:
• Обеспечение создания одного и только одного объекта класса
• Предоставление точки доступа для объекта, который является глобальным для программы
• Контроль одновременного доступа к ресурсам, которые являются общими
Простой способ реализации Singleton — сделать закрытым метод конструктора и создать статический метод, который выполняет инициализацию объекта. Таким образом, один объект создается при первом вызове, а класс будет всегда возвращать тот же объект при попытки новой инициализации объекта.
В Python мы реализуем эту идею по-другому, поскольку в нем нет возможности создавать приватные конструкторы.
Реализация классического синглтона в Python
Вот пример кода шаблона Singleton в Python v3.5. В этом примере мы делаем две основные вещи:
- Мы сделаем возможным создание только одного экземпляра класса Singleton.
- Если экземпляр существует, мы всегда будем использовать уже существующий объект.
class Singleton(object): def __new__(cls): if not hasattr(cls, 'instance'): cls.instance = super(Singleton, cls).__new__(cls) return cls.instance s = Singleton() print("Object created", s) s1 = Singleton() print("Object created", s1)
Вывод выполнения кода должен быть примерно таким:
('Object created', <__main__.Singleton object at 0x10ba9db90>) ('Object created', <__main__.Singleton object at 0x10ba9db90>)
В этом фрагменте кода мы переопределяем метод __new__ (специальный метод Python для создания объектов), что бы управлять созданием объекта. Объект s создается с помощью метода __new__, но перед этим он проверяет, существует ли уже созданный объект. Метод hasattr (специальный метод Python, позволяющий определить, имеет ли объект определенное свойство), используется для проверки наличия у объекта cls свойства instance. При создание объекта s, объект просто создается. В случае создания объекта s1, hasattr() обнаруживает, что у объекта уже существует свойство instance, и, следовательно, s1 использует уже существующий экземпляр объекта (расположенный по адресу 0x10ba9db90).
Отложенный экземпляр в Singleton
Одним из вариантов использования шаблона Singleton является отложенная инициализация. Например, в случае импорта модулей мы можем автоматически создать объект, даже если он не нужен. Отложенное создание экземпляра гарантирует, что объект создается, только тогда, когда он действительно необходим.
В следующем примере кода, когда мы используем s = Singleton(), вызывается метод __init__, но при этом новый объект не будет создан. Фактическое создание объекта произойдет, когда мы используем Singleton.getInstance().
class Singleton: __instance = None def __init__(self): if not Singleton.__instance: print(" __init__ method called..") else: print("Instance already created:", self.getInstance()) @classmethod def getInstance(cls): if not cls.__instance: cls.__instance = Singleton() return cls.__instance s = Singleton() ## class initialized, but object not created print("Object created", Singleton.getInstance()) # Object gets created here s1 = Singleton() ## instance already created
Singleton на уровне модуля
Все модули по умолчанию являются синглетонами из-за особенностей работы импорта в Python. Python работает следующим образом:
- Проверяет, был ли уже импортирован модуль.
- При импорте возвращает объект модуля. Если объекта не существует, то есть модуль не импортирован, он импортируется и создается его экземпляр.
- Когда модуль импортируется, он инициализируется. Но когда тот же модуль импортируется снова, он уже не инициализируется, что похоже на поведение Singleton, имеющим только один объект и возвращающим один и тот же объект.
Моностатический синглтон
В описание шаблона Singleton в книге Gang of Four говорится, что должен быть один и только один объект класса. Однако, согласно Алексу Мартелли, программисту обычно требуется, чтобы экземпляры имели одно и то же состояние. Он предлагает разработчикам больше беспокоиться о состоянии и поведении, а не об идентичности экземпляров. Поскольку концепция основана на том что бы все объекты имели одно и то же состояние, она также известна как шаблон Monostate.
Шаблон Monostate может быть реализован очень простым способом. В коде ниже мы присваиваем переменную __dict__ (специальную переменную Python) переменной класса __shared_state. Python использует __dict__ для хранения состояния каждого объекта класса. В следующем коде мы намеренно назначаем __shared_state всем созданным экземплярам. Поэтому, когда мы создаем два экземпляра, «b» и «b1», мы получаем два разных объекта. Однако состояния переменных b.__dict__ и b1.__dict__ одинаковы. Теперь, даже если переменная объекта x изменится в объекте b, изменение копируется в переменную __dict__, которая является общей для всех объектов, и b1 получит это изменение:
class Borg: __shared_state = {"1": "2"} def __init__(self): self.x = 1 self.__dict__ = self.__shared_state pass b = Borg() b1 = Borg() b.x = 4 print("Borg Object 'b': ", b) ## b and b1 are distinct objects print("Borg Object 'b1': ", b1) print("Object State 'b':", b.__dict__)## b and b1 share same state print("Object State 'b1':", b1.__dict__)
В результате должно получится что то типа такого:
("Borg Object 'b': ", <__main__.Borg instance at 0x10baa5a70>) ("Borg Object 'b1': ", <__main__.Borg instance at 0x10baa5638>) ("Object State 'b':", {'1': '2', 'x': 4}) ("Object State 'b1':", {'1': '2', 'x': 4})
Другой способ реализации класса Borg — это использование метода __new__. Как мы знаем, метод __new__ отвечает за создание экземпляра объекта:
class Borg(object): _shared_state = {} def __new__(cls, *args, **kwargs): obj = super(Borg, cls).__new__(cls, *args, **kwargs) obj.__dict__ = cls._shared_state return obj
Синглтоны и метаклассы
Начнем с краткого введения в метаклассы. Метакласс — это классы, экземпляры которых являются классами. С помощью метаклассов программисты получают возможность создавать классы своего собственного типа из предопределенных классов Python. Например, если у вас есть объект MyClass, вы можете создать метакласс MyKls, который переопределяет поведение MyClass так, как вам нужно.
Давайте разберемся с этим подробно.
Что было понятнее можно сказать что, метакласс это такая штука, которая создают объекты-классы. В Python все является объектом. Если мы пишем a = 5, тогда type(a) возвращает <type ‘int’>, что означает, что переменная a имеет тип int. Однако type(int) возвращает <type ‘type’>, что означает наличие метакласса, поскольку int является классом типа type.
Определение класса определяется его метаклассом, поэтому, когда мы хотим создать класс с помощью строки кода class A…, Python создает его с помощью A = type (name, base, dict), где:
• name: это название класса
• base: это базовый класс
• dict: это атрибуты класса
Теперь, если у класса есть предопределенный метакласс (по имени MetaKls), Python создает класс с помощью A = MetaKls(name, base, dict).
Рассмотрим пример реализации метакласса в Python 3.5:
class MyInt(type): def __call__(cls, *args, **kwds): print("***** Here's My int *****", args) print("Now do whatever you want with these objects...") return type.__call__(cls, *args, **kwds) class int(metaclass=MyInt): def __init__(self, x, y): self.x = x self.y = y i = int(4,5)
В итоге должно отобразиться что типа такого:
***** Here's My int ***** (4, 5) Now do whatever you want with these objects...
Специальный метод Python __call__ вызывается, когда необходимо создать объект для уже существующего класса. В этом коде, когда мы создаем экземпляр класса int с помощью int(4,5), вызывается метод __call__ метакласса MyInt, что означает, что метакласс теперь управляет созданием объекта.
Что то похожее что мы рассматривали раньше в шаблоне Singleton. Поскольку метакласс имеет больший контроль над созданием классов и созданием объектов, его можно использовать для создания синглетонов. Для управления созданием и инициализацией класса в метаклассах переопределяют методы __new__ и __init__.
Реализация Singleton с метклассами может быть лучше объяснена с помощью следующего примера кода:
class MetaSingleton(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super(MetaSingleton, cls).__call__(*args, **kwargs) return cls._instances[cls] class Logger(metaclass=MetaSingleton): pass logger1 = Logger() logger2 = Logger() print(logger1, logger2)
Первый пример использования Singleton
В качестве примера практического использования мы рассмотрим приложение базы данных. Рассмотрим пример облачной службы, которая включает в себя несколько операций чтения и записи в базе данных. Полный облачный сервис разбит на несколько сервисов, которые выполняют операции с базой данных.
Понятно, что общим ресурсом для разных сервисов является сама база данных. Итак, если нам нужно спроектировать облачный сервис, необходимо учесть следующие моменты:
- Согласованность операций в базе данных — одна операция не должна приводить к конфликтам с другими операциями
- Использование памяти и ЦП должно быть оптимальным для обработки нескольких операций с базой данных.
Пример реализации:
import sqlite3 class MetaSingleton(type): _instances = {} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls] = super(MetaSingleton, cls).__call__(*args, **kwargs) return cls._instances[cls] class Database(metaclass=MetaSingleton): connection = None def connect(self): if self.connection is None: self.connection = sqlite3.connect("db.sqlite3") self.cursorobj = self.connection.cursor() return self.cursorobj db1 = Database().connect() db2 = Database().connect() print ("Database Objects DB1", db1) print ("Database Objects DB2", db2)
В этом коде мы сделали следующее:
- Мы создали метакласс по имени MetaSingleton. Как мы объясняли в предыдущем разделе, специальный метод __call__ используется в метаклассе для создания Singleton.
- Класс Database создан с помощью метакласса MetaSingleton и является синглтон. Таким образом, когда создается экземпляр класса Database, он создает только один объект.
- Когда веб-приложение хочет выполнить определенные операции с БД, оно несколько раз создает экземпляр класса Database (в качестве примера, например в разных частях приложения), но создается только один объект. Поскольку существует только один объект, обращения к базе данных синхронизируются. Кроме того, такой подход позволяет ограничить использование системных ресурсов, и мы можем избежать ситуации нехватки памяти или ресурсов процессора.
Если предположить, что вместо одного веб-приложения у нас есть кластерная установка с несколькими веб-приложениями, но только с одной БД. То это не очень хорошая ситуация для Singletons, потому что с каждым добавлением нового веб-приложения создается новый Singleton и добавляется новый объект, который будет запрашивать базу данных. Это приводит к несинхронизированным операциям с базой данных и потребует больше ресурсов. В таких случаях будет лучше использовать пул соединений с базой данных, чем использование простого Singletons.
Второй пример использования Singleton
Давайте рассмотрим другой сценарий, в котором мы внедряем службы проверки работоспособности (например, Nagios) для нашей инфраструктуры. Мы создаем класс HealthCheck, который реализован как Singleton. Мы также будем поддерживать список серверов, для которых должна выполняться проверка работоспособности. Если сервер удален из этого списка, программное обеспечение для проверки работоспособности должно обнаружить его и удалить с серверов, настроенных для проверки.
В следующем коде объекты hc1 и hc2 являются экземплярами класса в Singleton. Серверы добавляются в инфраструктуру для проверки работоспособности с помощью метода addServer(). В начале выполняется, итерация проверки работоспособности для этих серверов. Затем метод changeServer() удаляет последний сервер и добавляет новый. А затем, когда снова запускается проверка во второй итерации то используется уже измененный список серверов.
Все это делается с Singletons. Когда серверы добавляются или удаляются, проверка работоспособности должна быть таким объектом, который знает об изменениях, внесенных в инфраструктуру:
class HealthCheck: _instance = None def __new__(cls, *args, **kwargs): if not HealthCheck._instance: HealthCheck._instance = super(HealthCheck, \ cls).__new__(cls, *args, **kwargs) return HealthCheck._instance def __init__(self): self._servers = [] def addServer(self): self._servers.append("Server 1") self._servers.append("Server 2") self._servers.append("Server 3") self._servers.append("Server 4") def changeServer(self): self._servers.pop() self._servers.append("Server 5") hc1 = HealthCheck() hc2 = HealthCheck() hc1.addServer() print("Schedule health check for servers (1)..") for i in range(4): print("Checking ", hc1._servers[i]) hc2.changeServer() print("Schedule health check for servers (2)..") for i in range(4): print("Checking ", hc2._servers[i])
Примечание:
Этот пример не будет работать в Python 3.3 и более поздних версиях, если вы переопределяете и __new__, и __init__, вам следует избегать передачи дополнительных аргументов перезаписываемым объектным методам. Если вы переопределяете только один из этих методов, разрешается передавать дополнительные аргументы другому (поскольку это обычно происходит без вашей помощи).
Пример переопределения __new__ Python 3.
class Employee(object): def __new__(cls,*args, **kwargs): if not hasattr(cls,'_inst'): print(cls) cls._inst = super(Employee, cls).__new__(cls) # если запустить код написаный ниже в Python3, он выдаст ошибку «TypeError: object() takes no parameters» # cls._inst = super(Employee, cls).__new__(cls, *args,**kwargs) return cls._inst
Итак в результате работы кода с классом HealthCheck, должно отобразиться что то типа такого:
Schedule health check for servers (1).. Checking Server 1 Checking Server 2 Checking Server 3 Checking Server 4 Schedule health check for servers (2).. Checking Server 1 Checking Server 2 Checking Server 3 Checking Server 5
Недостатки шаблона Singleton
При работе с синглтонами нужно учитывать не только их достоинства но и их недостатки. Поскольку у Singleton есть глобальная точка доступа, при его использовать нужно всегда помнить о его основном недостатке. Singleton — это по сути это одно неделимое глобальное состояние. Это может быть как достоинство так и недостаток управляемости. Могут быть проблемы с тестированием, расширением, или детерминированность отдельных частей кода. Все компоненты, использующие этот паттерн, оказываются жестко связанными. Связанное зачастую приходится развязывать — например, чтобы написать тесты. И, тестировать код, в котором очень часто используются сингелтоны, может стать проблемой.
Резюме
В этой статье вы узнали о шаблоне проектирования Singleton, о том что он используется, когда нужно иметь только один объект. Мы также рассмотрели различные способы реализации Singletons в Python. Классическая реализация допускает несколько попыток создания экземпляров, но всегда возвращает один и тот же объект. Также обсудили паттерн Monostate, который является вариацией паттерна Singleton. Monostate позволяет создавать несколько объектов, которые имеют одно и то же состояние.
Мы рассмотрели приложение, где Singleton может применяться для согласования операций с базами данных в нескольких сервисах.
Наконец, мы также рассмотрели главный недостаток Singletons.
Была ли вам полезна эта статья?
[15 / 4.7]
6. Синглтон (Singleton) · Шаблоны игрового программирования
- Шаблоны игрового программирования
Аннотация
I. Введение
1. Архитектура, производительность и игры
II. Обзор шаблонов проектирования
2. Команда (Command)
3. Приспособленец (Flyweight)
4. Наблюдатель (Observer)
5. Прототип (Protorype)
6. Синглтон (Singleton)
7. Состояние (State)
III. Последовательные шаблоны (Sequencing Patterns)
8. Двойная буферизация (Double Buffering)
9. Игровой цикл (Game Loop)
10. Метод обновления (Update Method)
IV. Поведенческие шаблоны (Behavioral Patterns)
11. Байткод (Bytecode)
12. Подкласс песочница (Subclass Sandbox)
13. Объект тип (Type Object)
V. Шаблоны уменьшения связности (Decoupling Patterns)
14. Компонент (Component)
15. Очередь событий (Event Queue)
16. Поиск службы (Service Locator)
VI. Шаблоны оптимизации(Optimization Patterns)
17. Локализация данных (Data Locality)
18. Грязный флаг (Dir
samtools — Что такое синглтон в биоинформатике?
Переполнение стека
- Около
Продукты
- Для команд
Переполнение стека
Общественные вопросы и ответыПереполнение стека для команд
Где разработчики и технологи делятся частными знаниями с коллегамиВакансии
Программирование и связанные с ним технические возможности карьерного ростаТалант
Нанимайте технических специалистов и создавайте свой бренд работодателяРеклама
Обратитесь к разработчикам и технологам со всего мира
.
Singleton — Unify Community Wiki
Альтернативы
Скриптируемые объекты
Отличной альтернативой одноэлементному шаблону в Unity является использование ScriptableObjects в качестве типа глобальной переменной. Райан Хиппл из Schell Games выступил с презентацией на Unite Austin 2017 под названием «Архитектура игры со сценариями», в которой объясняется, как их реализовать, а также многие преимущества перед одиночными играми.
Ящик для инструментов
Концепция «Toolbox» дополнительно улучшает одноэлементный шаблон, предлагая другой подход, который делает их более модульными и улучшает тестируемость.
Введение
Шаблон singleton — это способ гарантировать, что класс всегда имеет только один глобально доступный экземпляр. Во многом похож на обычный статический класс, но с некоторыми преимуществами. Это очень полезно для создания классов типа глобального менеджера, которые содержат глобальные переменные и функции, к которым должен иметь доступ многие другие классы. Тем не менее, удобство шаблона может легко привести к неправильному использованию и злоупотреблению, и это сделало его несколько спорным, поскольку многие критики считали его анти-шаблоном, которого следует избегать.Но, как и любой шаблон проектирования, синглтоны могут быть очень полезны в определенных ситуациях, и в конечном итоге разработчик должен решить, подходит ли он им.
Преимущества
- Доступен во всем мире. Нет необходимости искать или поддерживать ссылку на класс.
- Постоянные данные. Может использоваться для хранения данных по сценам.
- Поддерживает интерфейсы. Статические классы не могут реализовывать интерфейсы.
- Поддерживает наследование. Статические классы не могут быть присущи другому классу.
Преимущество использования синглтонов в Unity, а не статических параметров и методов, состоит в том, что статические классы загружаются лениво при первом обращении к ним, но должны иметь пустой статический конструктор (или он создается для вас). Это означает, что проще испортить и взломать код, если вы не будете осторожны и не будете знать, что делаете. Что касается использования паттерна синглтон, вы автоматически уже делаете много полезных вещей, таких как создание их с помощью метода статической инициализации и их неизменность.
Недостатки
- Необходимо использовать ключевое слово Instance (например,
.Instance) для доступа к одноэлементному классу. - Активным может быть только один экземпляр класса.
- Герметичные соединения. Изменение синглтона может легко нарушить работу всего остального кода, который от него зависит. Требуется много рефакторинга.
- Нет полиморфизма.
- Не очень тестируемый.
Реализация
Одноэлементный шаблон обычно применяется к нескольким классам, но реализация всегда одинакова.Таким образом, создание одноэлементного базового класса, от которого другие могут наследовать, является идеальным, поскольку оно устраняет необходимость повторно создавать один и тот же код для каждого класса, который должен быть одноэлементным.
Примечания:
- Этот сценарий не предотвратит использование конструкторов, не являющихся одноэлементными, в ваших производных классах. Чтобы предотвратить это, добавьте защищенный конструктор в каждый производный класс.
- При выходе из Unity он уничтожает объекты в случайном порядке, и это может создать проблемы для одиночных игр.Поэтому мы предотвращаем доступ к экземпляру синглтона при выходе из приложения, чтобы предотвратить проблемы.
Singleton.cs
с использованием UnityEngine; /// <резюме> /// Наследование от этого базового класса для создания синглтона. /// например открытый класс MyClassName: Singleton{} /// открытый класс Singleton : MonoBehaviour, где T: MonoBehaviour { // Проверяем, не собираемся ли мы быть уничтоженными. частный статический bool m_ShuttingDown = false; частный статический объект m_Lock = новый объект (); частный статический T m_Instance; /// <резюме> /// Доступ к экземпляру синглтона через это свойство./// общедоступный статический экземпляр T { получить { если (m_ShuttingDown) { Debug.LogWarning ("[Singleton] Instance '" + typeof (T) + "'уже уничтожено. Возвращается значение null."); return null; } замок (m_Lock) { если (m_Instance == null) { // Ищем существующий экземпляр. m_Instance = (T) FindObjectOfType (typeof (T)); // Создаем новый экземпляр, если он еще не существует.если (m_Instance == null) { // Необходимо создать новый GameObject, к которому будет прикреплен синглтон. var singletonObject = новый GameObject (); m_Instance = singletonObject.AddComponent (); singletonObject.name = typeof (T) .ToString () + «(Синглтон)»; // Сделаем экземпляр постоянным. DontDestroyOnLoad (singletonObject); } } return m_Instance; } } } частная пустота OnApplicationQuit () { m_ShuttingDown = true; } частная недействительность OnDestroy () { m_ShuttingDown = true; } }
Требования
В приведенном выше сценарии используется специальный метод расширения GetOrAddComponent, который не является частью Unity.
Использование
Чтобы сделать любой класс синглтоном, просто наследуйте от базового класса синглтона вместо MonoBehaviour, например:
открытый класс MySingleton: Singleton{ // (Необязательно) Предотвратить использование конструктора, отличного от одиночного элемента. protected MySingleton () {} // Затем добавляем любой код к классу, который вам нужен, как обычно. публичная строка MyTestString = "Привет, мир!"; }
Теперь вы можете получить доступ ко всем общедоступным полям, свойствам и методам из класса в любом месте, используя
открытый класс MyClass: MonoBehaviour { частная пустота OnEnable () { Debug.Log (MySingleton.Instance.MyTestString); } }
.Шаблон синглтона
— qaru Переполнение стека
- Около
Продукты
- Для команд
Переполнение стека
Общественные вопросы и ответы
Переполнение стека для команд
Где разработчики и технологи делятся частными знаниями с коллегами
Вакансии
Программирование и связанные с ним технические возможности карьерного роста
Талант
Нанимайте технических специалистов и создавайте свой бренд работодателя
Реклама
Обратитесь к разработчикам и технологам со всего мира
- О компании
.
singleton — Викисловарь
Английский [править]
Этимология [править]
Из single + -ton , вероятно, следуя модели simpleton .
Существительное [править]
одноэлементный ( множественного числа одиночный объект )
- (игральные карты) Игральная карта, единственная масть в руке, особенно в бридж.
- (игральные карты) Рука, содержащая только одну карту определенной масти.
- Отдельный объект, особенно один из группы.
- (вычисления) Класс, экземпляр которого не может быть создан более одного раза, то есть реализующий шаблон проектирования singleton.
- (математика) Набор ровно с одним элементом.
- Ребенок или животное, рожденные поодиночке, а не двойней или иным многоплодным ребенком.
одноплодные преждевременные роды
- Человек без романтического партнера.
- Человек без диссоциативной идентичности.
- (фонетика) Единственная согласная, в отличие от удвоенной согласной.
singleton sonorants
Antonyms [править]
Производные термины [править]
Переводы [править]
См. Также [править]
Произношение [править]
- IPA (ключ) : / ˈsɪŋɡəltɔn /, / ˈsɪŋəltɔn /
Существительное [править]
singleton m ( множественное число singleton , уменьшительное singletonnetje n )
- Синглтон (игральная карта-одиночка).
singleton n ( во множественном числе singletonnetje , уменьшительно singletonnetje n )
- Синглтон (шаблон проектирования, класс, набор).
Португальский [править]
Существительное [править]
одноэлементный м ( множественное число одноэлементное число )
- (вычисление) singleton (класс, экземпляр которого не может быть создан более одного раза)
.
Продукты
Переполнение стека
Общественные вопросы и ответы
Переполнение стека для команд
Где разработчики и технологи делятся частными знаниями с коллегами
Вакансии
Программирование и связанные с ним технические возможности карьерного роста
Талант
Нанимайте технических специалистов и создавайте свой бренд работодателя
Реклама
Обратитесь к разработчикам и технологам со всего мира
одноплодные преждевременные роды
singleton sonorants