Данная статья ориентирована на тех, кто впервые столкнулся с понятием паттернов, услышал о
И с блекджеком и цифрами и потратить на это много времени, а можно использовать уже давно описанный и реализовать его. То же самое и с паттернами. Плюс ко всему, с использованием паттернов код становится более стандартизирован, а при использовании нужных шаблонов у вас будет меньше вероятности сделать ошибки, так как их уже давно предвидели и устранили в этом паттернте. Ну и плюс ко всему, знание паттернов позволяет программистам лучше понимать друг друга. Достаточно просто произнести название шаблона, вместо того, чтобы пытаться объяснить своим коллегам-программистам, чего вы от них хотите.
Итак, подытожим, шаблоны проектирования помогают:
В заключении этого раздела отметим, что все многообразие паттернов можно упрощенно разбить на три большие группы:
Singleton
’e, либо каким-то образом его сделал, но так ничего и не поняли. Welcome! Впервые с паттернами студенты JavaRush сталкиваются на 15 уровне, когда неожиданным образом кэп просит “закрепить” и реализовать паттерн Singleton
с ленивой реализацией. У студентов, впервые услышавших про Singleton
, мгновенно возникает куча вопросов: что вообще такое паттерн, зачем он нужен, какой еще Singleton
и наконец, что еще за ленивая реализация. Начнем отвечать по-порядку:
Что вообще такое паттерн
Отвечать на этот вопрос для лучшего понимания, полагаю, стоит с истории. Среди программистов есть такая знаменитая четверка авторов: Эрих Гамма, Ричард Хелм, Ральф Джонсон и Джон Влиссидес, которым пришла в голову интересная мысль.Они заметили, что при написании программ им часто приходится решать приблизительно одни и те же задачи, и писать по структуре однотипный код. Поэтому они решили описать в виде паттернов типовые шаблоны, которые часто приходится использовать в объектно-ориентированном программировании. Книга вышла в 1995 году под названием «Приемы объектно-ориентированного проектирования. Паттерны проектирования» . Название книги оказалось слишком длинным, и ее просто стали называть «Книгой банды четырех». В первом издании было опубликовано 23 паттерна, после чего были открыты и десятки других. Так вот, отвечая на вопрос этого параграфа, — «Что же такое паттерны», подытожим буквально в нескольких словах:
Паттерн – это стандартизированное решение какой-либо часто встречающейся проблемы. |
Singleton
– это всего-лишь один из таких паттернов.
Зачем нужны паттерны (шаблоны проектирования)
Программировать получается и без знания паттернов, убедиться в этом можно просто осознав тот факт, что к 15-му уровню на JavaRush вы написали сотни мини-программ, ничего не зная об их существовании. Это говорит о том, что паттерн – это своего рода инструмент, наличие которого и отличает мастера от любителя:В паттернах описывается, как правильно следует решать одну из типовых задач. Как следствие, знание паттернов экономит ваше время. Можно привести аналогию с алгоритмами. К примеру, можно придумывать "свой" алгоритм сортировки
|
Наконец-то паттерн Singleton
Singleton
относится к порождающим паттернам. Его дословный перевод – одиночка. Этот паттерн гарантирует, что у класса есть только один объект (один экземпляр класса) и к этому объекту предоставляется глобальная точка доступа. Из описания должно быть понятно, что этот паттерн должен применяться в двух случаях:
- когда в вашей программе должно быть создано не более одного объекта какого-либо класса. Например, в компьютерной игре у вас есть класс «Персонаж», и у этого класса должен быть только один объект описывающий самого персонажа.
- когда требуется предоставить глобальную точку доступа к объекту класса. Другими словами, нужно сделать так, чтобы объект вызывался из любого места программы. И, увы, для этого не достаточно просто создать глобальную переменную, ведь она не защищена от записи и кто угодно может изменить значение этой переменной и глобальная точка доступа к объекту будет потеряна. Это свойства
Singleton
'a нужно, например, когда у вас есть объект класса, который работает с базой данных, и вам нужно чтобы к базе данных был доступ из разных частей программы. АSingleton
будет гарантировать, что никакой другой код не заменил созданный ранее экземпляр класса.
Singleton
: объект в программе должен быть один и к нему есть глобальный доступ. В примере на 15 уровне кэп просит реализовать этот паттерн для следующей задачи (вот ее описание):
Внимательно прочитав условие, становится понятно, зачем здесь нужен именно
Singleton
(Одиночка). Ведь в программе просят создать по одному объекту каждого класса: Sun
, Moon
, Earth
. И логично предположить, что каждый класс в программе должен создавать не больше одного Солнца/Луны/Земли, иначе это будет абсурд, если конечно вы не пишите свою версию звездных воин.
Особенность реализации Singleton
в Java за три шага
Поведение Одиночки на Java невозможно реализовать с помощью обычного конструктора, потому что конструктор всегда возвращает новый объект. Поэтому все реализации Singleton
’a сводятся к тому, чтобы скрыть конструктор и создать публичный статический метод, который будет управлять существованием объекта-одиночки и «уничтожать» всех вновь-появляющихся объектов. В случае вызова Singleton
’a он должен либо создать новый объект (если его еще нет в программе), либо вернуть уже созданный. Для этого:
#1. – Нужно добавить в класс приватное статическое поле, содержащее одиночный объект:
public class LazyInitializedSingleton {
private static LazyInitializedSingleton instance; //#1
}
#2. – Сделать конструктор класса (конструктор по-умолчанию) приватным (чтобы доступ к нему был закрыть за пределами класса, тогда он не сможет возвращать новые объекты):
public class LazyInitializedSingleton {
private static LazyInitializedSingleton instance;
private LazyInitializedSingleton(){} // #2
}
#3. – Объявить статический создающий метод, который будет использоваться для получения одиночки:
public class LazyInitializedSingleton {
private static LazyInitializedSingleton instance;
private LazyInitializedSingleton(){}
public static LazyInitializedSingleton getInstance(){ // #3
if(instance == null){ //если объект еще не создан
instance = new LazyInitializedSingleton(); //создать новый объект
}
return instance; // вернуть ранее созданный объект
}
}
Вышеописанный пример несколько топорный, ведь мы просто скрываем конструктор и предоставляем взамен стандартного конструктора свой метод. Так как эта статья направлена на то, чтобы студенты JavaRush’a смогли впервые соприкоснуться с этим паттерном (и паттернами в принципе), здесь не будут приведены особенности реализации более сложных Одиночек. Отметим лишь, что в зависимости от сложности программы может потребоваться более детальная доработка этого паттерна. Например, в многопоточной среде (см. тему Thread’ы), несколько разных потоков могут одновременно вызвать метод получения Одиночки, и описанный выше код перестанет работать, ибо каждый отдельный поток сможет создать сразу несколько экземпляров класса. Поэтому еще есть несколько разных подходов к созданию правильных Thread-safe одиночек. Но это уже другая история =)
И напоследок. Что же такое Ленивая Инициализация, о которой просил кэп
Ленивую инициализацию (Lazy Initialization) еще называют отложенной инициализацией. Это прием в программировании, когда ресурсоемкая операция (а создание объекта – это ресурсоемкая операция) выполняется по требованию, а не заблаговременно. Что в общем-то и происходит в нашем коде Singleton
’a. Другими словами, наш объект создается в момент обращения к нему, а не заранее. Не следует полагать, что понятие ленивой инициализации как-то жестко связана именно с Singleton
’ом. Отложенная инициализация также используется и в других порождающих паттернах проектирования, например в таких как Proxy (Заместитель) и Factory Method (Фабричный метод), но это тоже другая история =)
При подготовке материалов статьи использовались следующие источники:
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ