Паттерн Одиночка (Singleton) - описание (шаблон)
Primary tabs
Forums:
[Singleton]
Приведём описание паттерна по данным стандартным пунктам
Название и классификация
Одиночка - паттерн, относящийся к группе порождающих паттернов (шиблонов).
Назначение
Гарантирует, что у класса есть только один экземпляр (ещё точнее можно сказать, что у "класса данного типа может быть только один экземпляр"), и предоставляет к нему глобальную точку доступа.
Псевдоним
Английское название Singleton (одиночка) часто калькируется в русскоязычные тексты и паттерн Одиночка называют "Синглтоном". Мы же будем использовать русское название так как оно весьма удачно.
Мотивация
Для некоторых классов важно, чтобы существовал только один экземпляр.
Например:
- Хотя в системе может быть много принтеров, но возможен лишь один спулер.
- Должны быть только одна файловая система и единственный оконный менеджер.
- В цифровом фильтре может находиться только один аналого-цифровой преобразователь (АЦП). Бухгалтерская система обслуживает только одну компанию.
Как гарантировать, что у класса есть единственный экземпляр и что этот экземпляр легко доступен?
Глобальная переменная дает доступ к объекту, но не запрещает инстанцировать класс в нескольких экземплярах.
Более удачное решение достигается в том случае, если сам класс:
- контролирует то, что у него есть только один экземпляр
- может запретить создание дополнительных экземпляров, перехватывая запросы на создание новых объектов
- и он же способен предоставить доступ к своему экземпляру.
Это и есть назначение паттерна одиночка.
Применимость
Паттерн одиночка следует использовать, когда:
- должен быть ровно один экземпляр некоторого класса, легко доступный всем клиентам;
- единственный экземпляр должен расширяться путем порождения подклассов, и клиентам нужно иметь возможность работать с расширенным экземпляром без модификации своего кода.
Структура
Фактически сам паттерн описывает единственный класс:
Участники
Так как класс единственный - то и участник один - он сам:
Singleton (одиночка) обладает следующими свойствами:
- определяет операцию Instance, которая позволяет клиентам получать доступ к единственному экземпляру.Instance D это операция класса, то есть метод класса в терминологии Smalltalk или статическая функция-член в C++ (функция должна быть стаитческой для того чтобы к ней был доступ тогда когда объект ещё не создан);
- может нести ответственность за создание собственного уникального экземпляра.
Отношения
Клиенты получают доступ к экземпляру класса Singleton только через его операцию Instance
Результаты
У паттерна одиночка есть определенные достоинства:
- контролируемый доступ к единственному экземпляру
- уменьшение числа имён
- допускает уточнение операций и представления
- допускает переменное число экземпляров
- большая гибкость, чем у операций класса
1) Контролируемый доступ к единственному экземпляру.
Поскольку класс Singleton инкапсулирует свой единственный экземпляр, он полностью контролирует то, как и когда клиенты получают доступ к нему;
2) Уменьшение числа имен.
Паттерн одиночка - шаг вперед по сравнению с глобальными переменными. Он позволяет избежать засорения пространства
имен глобальными переменными, в которых хранятся уникальные экземпляры;
3) Допускает уточнение операций и представления.
От класса Singleton можно порождать подклассы, а приложение легко сконфигурировать экземпляром расширенного класса. Можно конкретизировать приложение экземпляром того класса, который необходим во время выполнения;
4) Допускает переменное число экземпляров.
Паттерн позволяет вам легко изменить свое решение и разрешить появление более одного экземпляра класса Singleton. Вы можете применять один и тот же подход для управления числом экземпляров, используемых в приложении. Изменить нужно будет лишь операцию, дающую доступ к экземпляру класса Singleton;
5) Большая гибкость, чем у операций класса.
Еще один способ реализовать функциональность одиночки - использовать операции класса, то есть статические функции-члены в C++ и методы класса в Smalltalk. Но оба этих приема препятствуют изменению дизайна, если потребуется разрешить наличие нескольких экземпляров класса. Кроме того, статические функции-члены в C++ не могут быть виртуальными, так что их нельзя полиморфно заместить в подклассах.
Реализация
При использовании паттерна одиночка надо рассмотреть следующие вопросы:
гарантирование единственного экземпляра
1) Гарантирование единственного экземпляра.
Паттерн одиночка устроен так, что тот единственный экземпляр, который имеется у класса, самый обычный, но больше одного экземпляра создать не удастся. Чаще всего для этого прячут операцию, создающую экземпляры, за операцией класса
(то есть за статической функцией-членом или методом класса), которая гарантирует создание не более одного экземпляра.
Данная операция имеет доступ к переменной, где хранится уникальный экземпляр, и гарантирует инициализацию переменной этим экземпляром перед возвратом ее клиенту. При таком подходе можно не сомневаться, что одиночка будет создан и инициализирован перед первым использованием.
В C++ операция класса определяется с помощью статической функции-члена Instance класса Singleton. В этом классе есть также статическая переменная (член instance, которая содержит указатель на уникальный экземпляр).
Класс Singleton объявлен следующим образом:
class Singleton{ // то, что мы будем использовать вместо конструктора // это единственная точка входа как для создания // так и для получения уже имеющейся сущности public: static Singleton * Instance(); protected: // прячем стандартный конструкутор Singleton(); private: static Singleton* _instance; // здесь будет хранится уникальный экземпляр };
А реализуется класс так(в C++ можно отдельно класс объявить и отдельно прописать реализацию):
Singleton*Singleton::_instance = 0; Singleton*Singleton::Instance() { // проверяем - создана ли уже данная сущность if (_instance == 0) { // проверка существования // если нет, то создаём новую _instance= new Singleton; } return _instance; // возвращаем объект-одиночку }
Проверку существования можно сделать иной (именно она опередляет "модификацию" одиночки) - например включить (реализовать) поиск по реестру - чтобы можно было
создавать целый каталог одиночек - где каждый будет в единственном экземпляре.
Подобного можно добивиться, например, передавая в Instance() некоторое имя (строку) - которое должно быть уникальным в случае если мы хотим создать новый экземпляр.
Пример кода
Рассмотрим пример реализации паттерна Одиночка на PHP.
Известные применения
Применяется во многих системах, моделирующих реальные объекты.
Родственные паттерны
С помощью паттерна одиночка могут быть реализованы многие паттерны.
Смотри описание:
- Log in to post comments
- 6363 reads