Паттерн Одиночка

Паттерн Одиночка – порождающий паттерн проектирования, гарантирующий, что в однопоточном приложении будет единственный экземпляр класса с глобальной точкой доступа.

Реализация: паттерн чрезвычайно прост, попробуем с его помощью создать машину для президента, которая будет существовать в единственном экземпляре. Создание приватного конструктора в классе будет неплохим первым шагом в достижении нашей цели, это позволит избежать создание одиночки другими классами, вторым шагом будет создание метода получения экземпляра класса. Если с конструктором все понятно, то с методом, который возвращает экземпляр нашего «одиночки», все несколько сложнее. Единственный класс приложения:

В классе две переменных: ссылка на сам объект класса (presidentCar) и переменная для хранения информации о бронировании машины. Для того, чтобы объект класса нельзя было создать из вне, конструктор класса был сделан приватным, в конструкторе задается начальное значение бронирования автомобиля в 120 мм. Для получения ссылки на объект используется статичный метод getInstance(). Два оставшихся метода getArmor() и setArmor(int armor) используются для получения информации о бронировании машины и ее изменении. В некоторых источниках рекомендуется для переменной экземпляра класса (presidentCar) использовать модификатор final. Давайте посмотрим, как это все работает:

Вывод:
120
250

И так, первой строчкой мы получаем ссылку на экземпляр класса PresidentCar и присваиваем ее переменной prCar. Второй строчкой выводим информацию о бронировании машины – 120 мм, значение было установлено приватным конструктором. Третьей строчкой мы меняем значение брони на 250 мм. Для того, чтобы убедиться, что в памяти создан только один экземпляр класса PresidentCar мы создаем еще одну переменную и через метод getInstance() получаем ссылку на объект класса PresidentCar. Последней строчкой проверяем информацию о бронировании, как видите объект в памяти остался прежний и вернул новое значение в 250 мм.

Вы, наверное, обратили внимание в определении паттерна на небольшое уточнение — «в однопоточном приложении», а если у нас есть необходимость в нескольких потоках, то как быть?

Первое изменение это – переменная presidentCar в ее объявлении теперь присутствует ключевое слово volatile, оно гарантирует, что параллельные потоки будут корректно с ней работать; второе изменение коснулось метода getInstance() – теперь в нем используется двойная проверка, если экземпляр класса не существует, то происходит вход в блок synchronized, другими словами синхронизация выполняется только при первом вызове, внутри этого блока снова проверяется создан ли экземпляр класса, если нет, то он создается. Для чего это сделано – синхронизация сама по себе очень затратная операция с точки зрения системных ресурсов и использовать ее при каждом вызове экземпляра класса нецелесообразно.
И так, самым главным плюсом данного патерна проектирования «Одиночка» является контролируемый доступ к единственному экземпляру класса.



Полный исходный код для однопоточного приложения:

Полный исходный код для многопоточного приложения:

Site Footer