среда, 1 августа 2012 г.

pattern: Singleton

Назначение
    Гарантирует, что у класса есть только один экземпляр, и предоставляет к нему глобальную точку доступа.

Использование шаблона в JDK
(примеры частично взяты с этого ресурса)


Вариации


"Эталонная" реализация (Lazy Singleton):
1. public class SomeClass {
2.    private static SomeClass instance = null;
3.    private SomeClass() {}
4.    public static synchronized SomeClass getInstance() {
5.        if (instance == null) {
6.            instance = new SomeClass();
7.        }
8.        return instance;
9.     }
10.}
Вопросы:
- можно ли в строке 1 поставить public final class?
- можно ли в строке 2 убрать static?
- можно ли в строке 3 убрать private?
- можно ли в строке 4 убрать synchronized?
- можно ли в строке 4 убрать static?
- можно ли убрать static одновременно в строках 2 и 4?
- можно ли убрать строки 5 и 7 (проверка)?
- что будет, если вызов конструктора в строке 6 бросит исключение (заменим строку 3 на private SomeClass() {throw new RuntimeException();})? Что произойдет при последующем вызове getInstance()? Каково значение поля instance?
- можно ли в строке 4 написать static final synchronized?

"Ранняя" загрузка (Early Singleton):
1. class SomeClass {
2.    private static SomeClass instance = new SomeClass();
3.    private SomeClass() {}
4.    public static SomeClass getInstance() {
5.        return instance;
6.    }
7.}
Вопросы:
- можно ли в строке 4 добавить synchronized?
- что будет, если вызов конструктора в строке 2 бросит исключение (заменим строку 3 на private SomeClass() {throw new RuntimeException();})? Что произойдет при последующем вызове getInstance()? Каково значение поля instance?


Множественная загрузка синглетона
В один сервлет-контейнер (Tomcat) можно задеплоить много раз один и тот же war (под разными context path). Предположим, что в war лежит синглетон. 
Вопрос:
- каким образом у разных war - разные синглетоны, если все war запущены в одной JVM? (почитайте про ClassLoader-ы)
- Есть ли возможность в Tomcat сделать синглетон, разделяемый различными war-ами? (почитайте про папку ??? в Tomcat)

"Скрытый" синглетон
Хотя есть возможность создавать много объектов данного типа, они все разделяют "одно состояние" (или "часть состояния" - не все поля статические).

1. class SomeClass {    
2.     private static int counter;
3.     public SomeClass() {}
4.     public synchronized void increment() {
5.         counter++;
6.     }
7.     public synchronized int getCounter() {
8.         return counter;
9.     }    
10.}
В данном случае, все объекты типа SomeClass разделяют общий counter. Может использоваться для сокрытия от пользователя того, что используется совместное состояние. Частая форма реализации кэшей.
Пример: возможный кэш для PreparedStatement в JDBC driver.
Пример: возможный кэш для ??? в JDBC driver.
Пример: возможный кэш для ??? в JDBC driver.
Пример: кэш первого уровня у Hibernate.
Пример: кэш второго уровня у Hibernate.


Конкурирующие потоки и синглетон

Синглетон и TDD

Multiton
    Пример с enum

Double-Checked Locking idiom
    Статья "The Double-Checked Locking is Broken Declaration"

Порядок конструирования синглетонов
Деструкция синглетона
Порядок деструкции синглетонов
Синглетоны в Servlet API
Синглетоны в JDBC
Синглетоны в IoC/DI-контейнерах (Spring, Guice)
Синглетоны в Servlet API
Синглетоны в OSGi