На очереди один из самых известных паттернов — Singleton (часто называемый Одиночка). Основная его задача — гарантировать, что класс будет иметь лишь единственный экземпляр и глобальную точку доступа к нему. В программировании часто встречаются ситуации, когда необходимо создать класс, который будет существовать только таким образом. Глобальные переменные здесь не годятся, поскольку дают доступ к классу, но не могут запретить его инстанцирование в нескольких экземплярах. В случае работы с шаблоном Singleton сам класс контролирует наличие единственного своего экземпляра и предоставляет доступ к нему.
Итак, Singleton используют в следующих случаях:
-
когда необходимо иметь лишь один экземпляр какого-либо конкретного класса, доступного любым клиентам;
-
когда единственный экземпляр данного класса способен расширяться через порождения подклассов, а клиенты имеют возможность работать с уже расширенным экземпляром, не внося никаких изменений в свой код.
У класса, реализующего шаблон Singleton, присутствует операция Instance, требующаяся для того, чтобы предоставить доступ к его единственному экземпляру. Надо понимать, что клиенты получают доступ к экземпляру данного класса только через операцию Instance и никак иначе.
Рассматриваемый паттерн обладает несомненными достоинствами. Выше уже упоминалось, что класс, реализующий шаблон Singleton, инкапсулирует свой единственный экземпляр. Именно благодаря этому он полностью контролирует то, каким образом и когда клиенты будут получать доступ к нему. Кроме того, Singleton позволяет избежать использования глобальных переменных, а значит, не придется засорять ими пространство имен для хранения уникальных экземпляров классов.
Довольно легко создавать и подклассы от класса, реализующего Singleton. Само приложение допустимо сконфигурировать уже расширенным классом. Естественно, можно будет конкретизировать приложение определенным экземпляром класса, нужным в данный момент для выполнения.
Также несложно изменить класс, реализующий Singleton, и предоставить ему возможность создавать более одного экземпляра класса. Это порождает некоторую гибкость, которая всегда может пригодиться в будущем.
К минусам данного шаблона проектирования стоит отнести лишь то, что глобальные объекты, как таковые, могут быть вредны для программы, поскольку препятствуют ее масштабируемости.
Ну а теперь приступайте к реализации класса с шаблоном Singleton. Пусть вашим классом станет планета Земля. Думаю, никто не сомневается в том, что она должна быть реализована в единственном экземпляре. Итак, в листинге 1 представлена реализация паттерна.
Объявлен класс с именем Earth. В нем присутствует одна-единственная локальная переменная под названием instance. Собственно, это и есть экземпляр класса, который вы возвратите в статическом методе Instance. В нем вы сначала проверите, инициализирована ли ваша переменная. Если нет, то инициализируйте ее. В конце вы просто возвращаете instance. Кстати, можно было бы реализовать Singleton-класс несколько иначе (листинг 2).
Отличие этого примера от предыдущего заключается в том, что здесь была инициализирована переменная сразу же в точке объявления. А в статическом методе Instance она была просто возвращена. В принципе никакой разницы между двумя этими способами реализации Singleton нет. А теперь проверьте, действительно ли у вас имеется один экземпляр класса (листинг 3).
Паттерн Singleton считается не только одним из самых популярных в мире объектно-ориентированного программирования, но и одним из самых простых для восприятия (если не самым простым). Код шаблона достаточно несложен, никаких подводных камней нет, а значит, реализовывать подобные классы очень легко. Однако из этого не следует, что стоит использовать их везде, где только можно. Всегда помните, что перед тем как вводить какой-то паттерн в ваш код, вы должны решить, действительно ли он так здесь необходим. Не используйте паттерны только потому, что вы можете это делать. Там, где они уместны, паттерны будут помогать, в противном же случае могут навредить. Для паттерна Singleton это справедливо вдвойне, поэтому тщательно продумывайте, стоит ли внедрять его в код, и изучайте шаблоны дальше вместе с нами.