Одиночка — это порождающий паттерн, который гарантирует существование только одного объекта определённого класса, а также позволяет достучаться до этого объекта из любого места программы.
Одиночка имеет такие же преимущества и недостатки, что и глобальные переменные. Его невероятно удобно использовать, но он нарушает модульность вашего кода.
Вы не сможете просто взять и использовать класс, зависящий от одиночки в другой программе. Для этого придётся эмулировать присутствие одиночки и там. Чаще всего эта проблема проявляется при написании юнит-тестов.
Признаки применения паттерна: Одиночку можно определить по статическому создающему методу, который возвращает один и тот же объект.
Наивный Одиночка (один поток)
Топорно реализовать Одиночку очень просто — достаточно скрыть конструктор и предоставить статический создающий метод.
Singleton.java: Одиночка
DemoSingleThread.java: Клиентский код
OutputDemoSingleThread.txt: Результаты выполнения
Наивный Одиночка (много потоков)
Тот же класс ведёт себя неправильно в многопоточной среде. Несколько потоков могут одновременно вызвать метод получения Одиночки и создать сразу несколько экземпляров объекта.
Singleton.java: Одиночка
DemoMultiThread.java: Клиентский код
OutputDemoMultiThread.txt: Результаты выполнения
Многопоточный Одиночка
Чтобы исправить проблему, требуется синхронизировать потоки при создании объекта-Одиночки.
Singleton.java: Одиночка
DemoMultiThread.java: Клиентский код
OutputDemoMultiThread.txt: Результаты выполнения
Хотите ещё?
Существует ещё с полдюжины способов реализации Одиночки в Java. Если интересно, можете ознакомиться с ними здесь: