Что такое объект синглтон
Singleton (Одиночка) или статический класс?
Статья будет полезна в первую очередь разработчикам, которые теряются на собеседованиях когда слышат вопрос «Назовите основные отличия синглтона от статического класса, и когда следует использовать один, а когда другой?». И безусловно будет полезна для тех разработчиков, которые при слове «паттерн» впадают в уныние или просят прекратить выражаться 🙂
Что такое статический класс?
Что такое Singleton (Одиночка)?
Один из порождающих паттернов, впервые описанный «бандой четырех» (GoF). Гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа. Мы не будем подробно рассматривать здесь этот паттерн, его предназначение и решаемые им задачи — в сети существует масса подробной информации о нем (например здесь и здесь). Отмечу лишь что синглтоны бывают потокобезопасные и нет, с простой и отложенной инициализацией.
А если нет разницы — зачем плодить больше?
Так в чем же все-таки разница между этими двумя сущностями и когда следует их использовать? Думаю что лучше всего это проиллюстрировать в следующей таблице:
Singleton | Static class | |
---|---|---|
Количество точек доступа | Одна (и только одна) точка доступа — статическое поле Instance | N (зависит от количества публичных членов класса и методов) |
Наследование классов | Возможно, но не всегда (об этом — ниже) | Невозможно — статические классы не могут быть экземплярными, поскольку нельзя создавать экземпляры объекты статических классов |
Наследование интерфейсов | Возможно, безо всяких ограничений | Невозможно по той же причине, по которой невозможно наследование классов |
Возможность передачи в качестве параметров | Возможно, поскольку Singleton предоставляет реальный объект | Отсутствует |
Контроль времени жизни объекта | Возможно — например, отложенная инициализация (или создание по требованию) | Невозможно по той же причине, по которой невозможно наследование классов |
Использование абстрактной фабрики для создания экземпляра класса | Возможно | Невозможно по причине осутствия самой возможности создания экземпляра |
Сериализация | Возможно | Неприменима по причине отсутствия экземпляра |
Рассмотрим подробнее перечисленные выше критерии.
Количество точек доступа
Конечно же имеются ввиду внешние точки доступа, другими словами — публичный контракт взаимодействия класса и его клиентов. Это удобнее проиллюстрировать с помощью кода:
Singleton в «канонической» реализации:
Наследование классов
С наследованием статических классов все просто — оно просто не поддерживается на уровне языка. С Singleton все несколько сложнее. Для удобства использования многие разработчики чаще всего используют следующую реализацию паттерна:
А поскольку множественное наследование в C# и в любом CLI-совместимом языке запрещено — это означает что мы не сможем унаследовать класс Session от любого другого полезного класса. Выходом является делагирование синглтону управления доступом к экземпляру объекта:
Наследование интерфейсов
Использование интерфейсов позволяет достичь большей гибкости, увеличить количество повторно используемого кода, повысить тестируемость, и, самое главное — избежать сильной связности объектов. Статические классы не поддерживают наследования в принципе. Синглтон, напротив, наследование интерфейсов поддерживает в полной мере, поскольку это обычный класс. Но вот использовать эту возможность стоит только в том случае, если экземпляр синглтона планируется передавать в качестве входных параметров в смешанных сценариях или транслировать за границу домена. Пример смешанного сценария:
Возможность передачи в качестве параметров
Для статических классов это не поддерживается — можно передать разве что тип, но в большинстве ситуаций это бесполезно, за исключением случаев применения механизмов отражения (reflection). Синглтон же по сути является обычным экземпляром объекта:
Контроль времени жизни объекта
Время жизни статического класса ограничено временем жизни домена — если мы создали этот домен вручную, то мы косвенно управляем временем жизни всех его статических типов. Временем жизни синглтона мы можем управлять по нашему желанию. Яркий пример — отложенная инициализация:
Можно также добавить операцию удаления экземпляра синглтона:
Данная операция является крайне небезопасной, поскольку синглтон может хранить некоторое состояние и поэтому его пересоздание может иметь нежелательные последствия для его клиентов. Если все же необходимость в таком методе возникла (что скорее всего указывает на ошибки проектирования) то нужно постараться свести к минимуму возможное зло от его использования — например сделать его закрытым и вызывать внутри свойства Instance при определенных условиях:
Использование абстрактной фабрики для создания экземпляра класса
Статический класс не поддерживает данной возможности ввиду того, что нельзя создать экземпляр статического класса. В случае с синглтоном все выглядит просто:
Правда в варианте с аггрегацией синглтона придеться применить не совсем красивое и, немного громоздкое решение:
Сериализация
Сериализация применима только к экземплярам классов. Статический класс не может иметь экзмпляров поэтому сериализовать в данном случае нечего.
Так что же использовать Синглтон или Статический класс?
В любом случае выбор решения зависит от разработчика и от специфики решаемой им задачи. Но, в любом случае, можно сделать следующие выводы:
Синглтоны и общие экземпляры
Каждый раз при обсуждении программного обеспечения с другими разработчиками всплывает тема синглтонов, особенно в контексте развития WordPress’а. Я часто пытаюсь объяснить, почему их надо избегать, даже если они считаются стандартным шаблоном.
В данной статье я попытаюсь раскрыть тему того, почему синглтоны никогда не должны использоваться в коде и какие есть альтернативы для решения похожих проблем.
Что такое синглтон?
Синглтон — это шаблон проектирования в разработке программного обеспечения, описанный в книге Design Patterns: Elements of Reusable Object-Oriented Software (авторы — Банда четырёх), благодаря которой о шаблонах проектирования заговорили как об инструменте разработки ПО.
Идея в том, что вам может потребоваться, чтобы существовал лишь один экземпляр класса и чтобы вы предоставляли глобальную единую точку доступа к нему.
Это на самом деле достаточно просто объяснить и понять, и для многих людей синглтон — это лёгкий вход в мир шаблонов проектирования, что делает его самым популярным шаблоном.
Синглтон популярен, он был одним из первых шаблонов, описанных и стандартизированных в книге. Как же так получается, что некоторые разработчики считают его антишаблоном? Неужели он может быть настолько плохим?
Но синглтоны полезны и важны!
Я заметил, что многие люди путают два смежных понятия. Когда они говорят, что им нужен синглтон, им на самом деле нужно использовать один экземпляр объекта в разных операциях инстанцирования. В общем, когда вы создаёте инстанс, вы создаёте новый экземпляр этого класса. Но для некоторых объектов нужно всегда использовать один и тот же общий экземпляр (shared instance) объекта, вне зависимости от того, где он используется.
Но синглтон не является верным решением для этого.
Именно из-за второй функции люди выбирают синглтон, но эту задачу должен решать другой объект.
Нет ничего плохого в общем экземпляре. Но объект, который вы хотите для этого использовать, — не место для такого ограничения.
Ниже я покажу несколько альтернатив. Но сначала хочу рассказать, какие проблемы может вызвать синглтон.
Проблемы с синглтоном
Синглтон и SOLID
Прежде всего, и это может показаться скорее теоретической проблемой, синглтон нарушает многие принципы SOLID.
Шаблон синглтон нарушает четыре из пяти принципов SOLID. Он, возможно, хотел бы нарушить и пятый, если бы только мог иметь интерфейсы…
Легко сказать, что ваш код не работает только из-за каких-то теоретических принципов. И хотя, согласно моему собственному опыту, эти принципы — самое ценное и надёжное руководство, на которое можно опираться при разработке программного обеспечения, я понимаю, что просто слова «это факт» для многих звучат неубедительно. Мы должны проследить влияние синглтона на вашу повседневную практику.
Использования шаблона синглтон
Здесь перечислены недостатки, с которыми можно столкнуться, если иметь дело с синглтоном:
Вы не можете передавать/внедрять аргументы в конструктор. Поскольку при первом вызове синглтона реально исполняется только конструктор и вы не можете знать заранее, какой код первым обратится к синглтону, то во всём потребляющем коде нужно использовать один и тот же набор аргументов для передачи в конструктор, что во многих случаях почти невыполнимо, а вначале вообще бессмысленно. В результате синглтон делает бесполезным основной механизм инстанцирования в ООП-языках.
Вы не можете имитировать (mock away) синглтон при тестировании компонентов, использующих его. Это делает почти невозможным корректное модульное тестирование, потому что вы не добьётесь полной изоляции тестируемого кода. Проблема вызвана даже не самой логикой, которую вы хотите тестировать, а произвольным ограничением инстанцирования, в которое вы её оборачиваете.
Так как синглтон — глобально доступная конструкция, которая используется всей вашей кодовой базой, то идут прахом любые усилия по инкапсуляции, отчего появляются те же проблемы, что и в случае с глобальными переменными. То есть, как бы вы ни пытались изолировать синглтон в инкапсулированной части кода, любой другой внешний код может привести к побочным эффектам и багам в синглтоне. А без надлежащей инкапсуляции выхолащиваются сами принципы ООП.
Если у вас когда-либо был сайт или приложение, разросшееся настолько, что синглтону DatabaseConnection неожиданно понадобилось подключение ко второй, отличной от первой базе данных, значит, вы в беде. Придётся заново пересмотреть саму архитектуру и, возможно, полностью переписать значительную часть кода.
Все тесты, прямо или косвенно использующие синглтон, не могут корректно переключаться с одного на другой. Они всегда сохраняют состояние посредством синглтона, что может привести к неожиданному поведению там, где ваши тесты зависят от очерёдности запуска, или оставшееся состояние скроет от вас реальные баги.
Альтернативы синглтону
Я не хочу быть тем человеком, который во всём видит плохое, но не может предложить решение проблемы. Хотя я считаю, что вы должны оценивать всю архитектуру приложения, чтобы решить, как первым делом избежать использования синглтона, я предлагаю несколько самых распространённых способов в WordPress, когда синглтон можно легко заменить механизмом, который удовлетворяет всем требованиям и лишён большинства недостатков. Но прежде чем рассказать об этом, я хочу отметить, почему все мои предложения — только компромисс.
Существует «идеальная структура» для разработки приложений. Теоретически лучший вариант — единственный инстанцирующий вызов в загрузочном коде, создающий дерево зависимости приложения целиком, сверху донизу. Это будет работать так:
С помощью одного вызова выстроится сверху донизу весь стек приложения с внедрением зависимостей по мере необходимости. Цели такого подхода:
Однако, как бы хорошо это ни звучало, в WordPress’е так сделать невозможно, так как он не предоставляет централизованный контейнер или механизм внедрения, все плагины/темы загружаются изолированно.
Держите это в уме, пока мы будем обсуждать подходы. Идеальное решение, при котором весь стек WordPress’а инстанцируется через централизованный механизм внедрения, нам недоступно, поскольку оно требует поддержки WordPress Core. Всем описываемым далее подходам свойственны те или иные общие недостатки вроде сокрытия зависимостей посредством обращения к ним напрямую из логики вместо их внедрения.
Код синглтона
Пример кода с использованием синглтон-подхода, который мы будем сравнивать с другими:
Я не включил сюда все подробности реализации, с которыми часто загружаются синглтоны, потому что они неважны для теоретической дискуссии.
Фабричный метод
Учитывая название шаблона, вы можете подумать, что он больше похож на код Java, чем PHP-код, так что не стесняйтесь отклоняться от слишком строгого (и ленивого) соглашения об именовании и называйте фабрику более изобретательно.
Пример фабричного метода:
Приведённая версия фабрики избавлена почти от всех ранее описанных недостатков, за одним исключением.
Статичные заместители
Статичный заместитель (Static Proxy) — другой шаблон проектирования, на который можно поменять синглтон. Он подразумевает ещё более тесную связь, чем фабрика, но это хотя бы связь с абстракцией, а не с конкретной реализацией. Идея в том, что у вас есть статичное сопоставление (static mapping) интерфейса, и эти статичные вызовы прозрачно перенаправляются конкретной реализации. Таким образом, прямой связи с фактической реализацией нет, и статичный заместитель сам решает, как выбирать реализацию для использования.
Как видите, статичный заместитель создаёт очень короткий и чистый API. К недостаткам можно отнести то, что возникает тесная связь кода с сигнатурой класса. При использовании в правильном месте особых проблем это не вызывает, так как это связь с абстракцией, которую можно контролировать напрямую, а не с конкретной реализацией. Вы всё ещё можете заменить код одной базы данных на код другой, который вы считаете нужным, а реализация всё ещё является совершенно нормальным объектом, который может быть протестирован.
API WordPress Plugin
API WordPress Plugin может заменить синглтоны, когда те используются ради возможности обеспечения глобального доступа через плагины. Это самое чистое решение с учётом ограничений WordPress’а, с оговоркой, что вся инфраструктура и архитектура вашего кода привязывается к API WordPress Plugin. Не применяйте этот способ, если вы собираетесь заново использовать ваш код в разных фреймворках.
Один из основных компромиссов состоит в том, что ваша архитектура напрямую привязана к API WordPress Plugin. Если вы планируете когда-либо предоставлять функциональность плагина для Drupal-сайтов, то код придётся полностью переписать.
Другая возможная проблема — теперь вы зависите от тайминга WordPress-перехватчиков (hooks). Это может привести к багам, связанным с таймингом, их зачастую трудно воспроизвести и исправить.
Service Locator
Локатор служб — это одна из форм контейнера инверсии управления (Inversion of Control Container). Некоторые сайты описывают метод как антишаблон. С одной стороны, это правда, но с другой, как мы уже обсуждали выше, все предложенные здесь рекомендации можно считать лишь компромиссами.
Локатор служб — это контейнер, который предоставляет доступ к службам, реализованным в других местах. Контейнер по большей части — это коллекция экземпляров, сопоставленных с идентификаторами. Более сложные реализации локатора служб могут привносить такие возможности, как ленивое инстанцирование или генерирование заместителей.
Однако всё ещё нет ответа на вопрос, нужно ли пользоваться антишаблоном локатор служб вместо антишаблона синглтон… С локатором служб связана проблема: он «прячет» зависимости. Представим кодовую базу, которая использует правильное внедрение конструктора. В таком случае достаточно взглянуть на конструктор конкретного объекта, и можно сразу понять, от какого объекта он зависит. Если объект имеет доступ к ссылке на локатор служб, то вы можете обойти это явное разрешение зависимостей и извлечь ссылку (а следовательно, начать зависеть) на любой объект из реальной логики. Вот что имеют в виду, когда говорят, что локатор служб «прячет» зависимости.
Но, учитывая контекст WordPress, мы должны принять тот факт, что с самого начала нам недоступно идеальное решение. Нет технических возможностей реализовать правильное внедрение зависимостей по всей кодовой базе. Это значит, что нам в любом случае придётся искать компромисс. Локатор служб — не идеальное решение, однако этот шаблон хорошо укладывается в легаси-контекст и как минимум позволяет вам собрать все «компромиссы» в одном месте, а не раскидывать их по кодовой базе.
Внедрение зависимостей
Если вы работаете только в собственном плагине и вам не надо предоставлять доступ к своим объектам другим плагинам, то вам повезло: вы можете использовать настоящее внедрение зависимостей, чтобы избежать глобального доступа к зависимостям.
Выглядит немного сложнее, но имейте в виду, что мы должны были написать базовую версию всего плагина, чтобы продемонстрировать внедрение зависимостей.
Хотя у нас не может быть полного внедрения зависимостей во всём приложении, но мы, по крайней мере, можем получить его с ограничениями в плагине.
Это пример того, как всё соединить (wiring) вручную с помощью явного инстанцирования самих зависимостей. В более сложной кодовой базе вам захочется использовать автосоединяющееся внедрение зависимостей (Dependency Injector) (специализированный контейнер), которое принимает предварительную информацию о конфигурации и может рекурсивно инстанцировать целое дерево за один вызов.
Вот пример того, как можно сделать это соединение с помощью такого внедрения зависимостей (даны те же классы/интерфейсы, как и в предыдущем примере):
Комбинации
Для более сложных потребностей, которые разбросаны по нескольким пользовательским и сторонним плагинам, рассмотрите способы комбинирования рассмотренных подходов, которые не будут противоречить вашим условиям.
Например, в более сложных проектах я использовал следующий подход, чтобы приблизиться к идеальному решению, который описано выше:
На странице Bright Nucleus Architecture вы можете почитать об этом подходе и посмотреть записи.
Заключение
Несколько возможных подходов позволяют избавиться от синглтонов. Хотя ни один из них не идеален в контексте WordPress’а, они все без исключения предпочтительней синглтона.
Помните, что связанные с синглтонами проблемы заключаются не в том, что те расшарены, а в том, что синглтоны заставляют инстанцировать их самих.
Если вы знаете ситуации, когда синглтон — единственное подходящее решение, пишите в комментариях!
Паттерны проектирования, взгляд iOS разработчика. Часть 0. Синглтон-Одиночка
Я почув і забув.
Я записав і запам’ятав.
Я зробив і зрозумів.
Я навчив іншого, тепер я майстер.
(В. В. Бублик)
Небольшое вступление.
Я не зря вынес в начало поста цитату на украинском языке. Дело в том, что именно эти слова я услышал от своего преподавателя программирования на втором курсе университета, и именно в таком виде я вспоминаю эти слова до сих пор. Как вы можете догадаться, эта цитата является отсылкой к высказыванию Конфуция, но в ней есть очень важное дополнение о достижении мастерства.
И именно эти слова и сподвигли меня на написание данной серии постов. Дело в том, что я — начинающий iOS разработчик, и я очень хочу разобраться в паттернах проектирования. И я не придумал лучшего способа, чем взять книгу «Паттерны проектирования» Эрика и Элизабет Фримен, и написать примеры каждого паттерна на Objective-C и Swift. Таким образом я смогу лучше понять суть каждого паттерна, а также особенности обоих языков.
Содержание:
Итак, начнем с самого простого на мой взгляд паттерна.
Одиночка, он же — синглтон.
Итак, разберемся что такое синглтон в Objective-C и Swift на примерах из книги.
Давайте сначала узнаем как вообще создать объект какого-нибудь класса. Очень просто:
И тут авторы подводят нас к мысли, что приведенным выше способом можно создать сколько угодно объектов этого класса. Таким образом, первое что нужно сделать на пути к синглтону — запретить создание объектов нашего класса извне. В этом нам поможет приватный инициализатор.
И если в swift это реализуется тривиально:
Таким образом попытка создать объект нашего класса извне вызовет ошибку на этапе компиляции. Окей. Теперь и в objective-c у нас есть запрет на создание объектов нашего класса. Правда это еще не совсем приватный инициализатор, но мы к этому вернемся через пару секунд.
Итак, по сути мы получили класс, объекты которого не могут создаваться, потому что конструктор — приватный. И что со всем этим делать? Будем создавать объект нашего класса внутри нашего же класса. И будем использовать для этого статический метод (метод класса, а не объекта):
И если для swift опять все просто и понятно, то с objective-c возникает проблема с инициализацией:
(да, и не забудьте вынести метод + (instancetype)sharedInstance в файл заголовка, он должен быть публичным)
Теперь все компилируется и мы можем получать объекты нашего класса таким способом:
Наш синглтон почти готов. Осталось только исправить статический метод так, чтобы объект создавался только один раз:
Как видите, для этого нам понадобилась статическая переменная, в которой и будет храниться единожды созданный объект нашего класса. Каждый раз при вызове нашего статического метода она проверяется на nil и, если объект уже создан и записан в эту переменную — он не создается заново. Наш синглтон готов, ура! 🙂
Теперь немного примеров из жизни из книги.
Итак, у нас есть шоколадная фабрика и для приготовления мы используем высокотехнологичный нагреватель шоколада с молоком (я просто обожаю молочный шоколад), который будет управляться нашим программным кодом:
Как видите — нагреватель сначала заполняется смесью ( fill ), затем доводит ее до кипения ( boil ), и после — передает ее на изготовление молочных шоколадок ( drain ). Для избежания проблем нам нужно быть уверенными, что в нашей программе присутствует только один экземпляр нашего класса, который управляет нашим нагревателем, поэтому внесем изменения в программный код:
Итак, все отлично. Мы на 100% уверены (точно на 100%?), что у нас есть только один объект нашего класса и никаких непредвиденных ситуаций на фабрике не произойдет. И если наш код на objective-c выглядит довольно неплохо, то swift выглядит недостаточно swifty. Попробуем его немного переписать:
А как же многопоточность?
Все будет работать хорошо ровно до того момента, как мы захотим применить в нашей программе работу с потоками. Как же сделать наш синглтон потокобезопасным?
И опять же: в swift, как оказывается, совершенно не нужно выполнять каких-либо дополнительных действий. Константа уже потокобезопасна, ведь значение в нее может быть записано только один раз и это сделает тот поток, который доберется до нее первым.
А вот в objective-c необходимо внести коррективы в наш статический метод:
Блок внутри dispatch_once гарантированно выполнится только один раз, когда самый первый поток до него доберется, все остальные потоки — будут ждать, когда закончится выполнение блока.
Итоги подведем.
Итак, мы разобрались как правильно писать синглтоны на objective-c и swift. Приведу вам итоговый код класса Singleton на обоих языках:
Хочу попросить всех читателей и комментаторов: если вы увидели какую-нибудь неточность или знаете как какой-либо из приведенных мною кусков кода написать правильнее/красивее/корректнее — скажите об этом. Я пишу здесь совсем не для того, чтоб учить других, а для того, чтоб научиться самому. Ведь пока мы учимся — мы остаемся молодыми.
Синглтон (Перевод с английского главы «Singleton» из книги «Pro Objective-C Design Patterns for iOS» Carlo Chung)
Класс синглтона в объектно-ориентированном приложении всегда возвращает один и тот же экземпляр самого себя. Он обеспечивает глобальную точку доступа для ресурсов, которые предоставляет объект класса. Паттерн с такой функциональностью называется Синглтон.
В этой главе мы изучим возможности реализации и использования паттерна Синглтон в Objective-C и фреймворке Cocoa Touch на iOS.
Что из себя представляет паттерн Синглтон?
Паттерн Синглтон – едва ли не самый простой из паттернов. Его назначение в том, чтобы сделать объект класса единственным экземпляром в системе. В первую очередь нужно запретить создавать более одного экземпляра класса. Для этого можно использовать фабричный метод (глава 4), который должен быть статическим, так как не имеет смысла разрешать экземпляру класса создавать другой единственный экземпляр. Рисунок 7-1 показывает структуру класса простого синглтона.
Рисунок 7-1. Статическая структура паттерна Синглтон.
Примечание. Паттерн Синглтон: Проверяет, что есть только один экземпляр класса и обеспечивает единую точку доступа к нему.*
*Исходное определение, представленное в «Design Patterns» GoF (Addison-Wesley,
1994).
Когда можно использовать паттерн Синглтон?
Метод класса предоставляет возможность разделения без создания его объекта. Единственный экземпляр ресурса поддерживается в методе класса. Однако этот подход имеет недостаток гибкости в случае, если класс требует наследования для обеспечения большей функциональности.
Класс Синглтона может гарантировать единую, согласованную и хорошо известную точку доступа для создания и доступа к единственному объекту класса. Паттерн обеспечивает такую гибкость, что любой из его подклассов может переопределить метод создания экземпляра и иметь полный контроль над созданием объекта класса без изменения кода клиента. Еще лучше то, что реализация метода создания экземпляра может обрабатывать создание объекта динамически. Реальный тип класса может определяться во время выполнения, чтобы быть уверенным, что создается корректный объект. Эта техника будет обсуждаться дальше.
Существует также гибкая версия паттерна Синглтон, в которой фабричный метод всегда возвращает один и тот же экземпляр, но можно в дополнение аллоцировать и инициализировать другие экземпляры. Эта менее строгая версия паттерна обсуждается в разделе «Использование класса NSFileManager» далее в этой главе.
Реализация Синглтона в Objective-C
Есть кое-что, над чем стоит подумать, чтобы спроектировать класс Синглтона правильно. Первый вопрос, которым нужно задаться, — это как удостовериться, что только один экземпляр класса может быть создан? Клиенты в приложении, написанном на других объектно-ориентированных языках, таких, как C++ и Java, не могут создать объект класса, если его конструктор объявлен закрытым. А как обстоят дела в Objective-C?
Любой Objective-C метод является открытым, и язык сам по себе динамически типизированный, поэтому любой класс может послать сообщение другому (вызов метода в C++ и Java) без значительных проверок во время компиляции (только предупреждения компилятора, если метод не объявлен). Также фреймворк Cocoa (включая Cocoa Touch) использует управление памятью методом подсчета ссылок для поддержания времени жизни объекта в памяти. Все эти особенности делают реализацию Синглтона в Objective-C довольно непростой.
В оригинальном примере книги «Паттерны проектирования» пример Синглтона на C++ выглядел, как показано в листинге 7-1.
Листинг 7-1. Исходный пример на C++ паттерна Синглтон из книги «Паттерны проектирования».
Как описано в книге, реализация в C++ проста и прямолинейна. В статическом методе Instance() статическая переменная _instance проверяется на 0 ( NULL ). Если так, то создается новый объект класса Singleton и затем возвращается. Кто-то из вас может подумать, что Objective-C версия не сильно отличается от своего собрата и должна выглядеть, как в листингах 7-2 и 7-3.
Листинг 7–2. Объявление класса Singleton в Singleton.h
Листинг 7–3. Реализация метода sharedInstance Singleton.m
Листинг 7–4. Более подходящая реализация Singleton в Objective-C
Наследование от Синглтона
Если использовать трюк с NSAllocateObject для создания экземпляра, то он станет таким:
Теперь неважно, инстанцируем ли мы класс Singleton или какой-то из его подклассов, эта версия сделает все корректно.
Потокобезопасность
Использование Синглтонов во фреймворке Cocoa Touch
Использование класса UIApplication
Использование класса UIAccelerometer
Использование класса NSFileManager
Если нужно реализовать «строгий» синглтон, необходима реализация, похожая на пример, описанный в предыдущих разделах. Иначе – не переопределяйте allocWithZone: и другие связанные методы.