Рубрики

Синглтон Дизайн Шаблон | Реализация

Синглтон Дизайн Шаблон | Вступление

Шаблон Singleton — это один из самых простых шаблонов проектирования. Иногда нам нужно иметь только один экземпляр нашего класса, например, одно соединение с БД, совместно используемое несколькими объектами, поскольку создание отдельного соединения с БД для каждого объекта может быть дорогостоящим. Точно так же в приложении может быть один менеджер конфигурации или менеджер ошибок, который обрабатывает все проблемы, а не создает несколько менеджеров.

Определение:
Шаблон singleton — это шаблон проектирования, который ограничивает создание экземпляра класса одним объектом.
Давайте посмотрим различные варианты дизайна для реализации такого класса. Если вы хорошо разбираетесь в переменных статического класса и обращаетесь к модификаторам доступа, это не должно быть трудной задачей.


Метод 1: Классическая реализация

// Классическая Java-реализация синглтона
// дизайн шаблона

class Singleton

{

    private static Singleton obj;

  

    // закрытый конструктор для принудительного использования

    // getInstance () для создания объекта Singleton

    private Singleton() {}

  

    public static Singleton getInstance()

    {

        if (obj==null)

            obj = new Singleton();

        return obj;

    }

}

Здесь мы объявили getInstance () static, чтобы мы могли вызывать его без создания экземпляра класса. При первом вызове getInstance () он создает новый одноэлементный объект, а после этого просто возвращает тот же объект. Обратите внимание, что объект Singleton obj не создается до тех пор, пока он нам не понадобится, и не вызовем метод getInstance (). Это называется ленивым воплощением.

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

Эта последовательность выполнения создает два объекта для синглтона. Поэтому эта классическая реализация не является поточно-ориентированной.


Способ 2: сделать getInstance () синхронизированным

// Поток Синхронизированная реализация Java
// шаблон дизайна синглтона

class Singleton

{

    private static Singleton obj;

  

    private Singleton() {}

  

    // Только один поток может выполнить это одновременно

    public static synchronized Singleton getInstance()

    {

        if (obj==null)

            obj = new Singleton();

        return obj;

    }

}

Здесь использование synchronized гарантирует, что только один поток может одновременно выполнять getInstance ().
Основным недостатком этого метода является то, что использование синхронизации каждый раз при создании одноэлементного объекта обходится дорого и может снизить производительность вашей программы. Однако, если производительность getInstance () не критична для вашего приложения, этот метод обеспечивает чистое и простое решение.


Способ 3: нетерпеливое использование

// Статическая инициализация на основе Java-реализации
// шаблон дизайна синглтона

class Singleton

{

    private static Singleton obj = new Singleton();

  

    private Singleton() {}

  

    public static Singleton getInstance()

    {

        return obj;

    }

}

Здесь мы создали экземпляр синглтона в статическом инициализаторе. JVM выполняет статический инициализатор, когда класс загружается, и, следовательно, это гарантированно является потокобезопасным. Используйте этот метод только в том случае, если ваш одноэлементный класс легкий и используется во время исполнения вашей программы.


Метод 4 (лучший): используйте « Двойную проверку блокировки »

Если вы внимательно заметите, как только объект создан, синхронизация больше не будет полезна, потому что теперь obj не будет нулевым, и любая последовательность операций приведет к согласованным результатам.
Таким образом, мы получим блокировку getInstance () только один раз, когда объект равен нулю. Таким образом, мы синхронизируем только первый путь, то, что мы хотим.

// Двойная проверка блокировки на основе реализации Java
// шаблон дизайна синглтона

class Singleton

{

    private volatile static Singleton obj;

  

    private Singleton() {}

  

    public static Singleton getInstance()

    {

        if (obj == null)

        {

            // Чтобы сделать поток безопасным

            synchronized (Singleton.class)

            {

                // проверить снова как несколько потоков

                // может достичь выше уровня

                if (obj==null)

                    obj = new Singleton();

            }

        }

        return obj;

    }

}

Мы объявили obj volatile, которое гарантирует, что несколько потоков правильно предлагают переменную obj, когда она инициализируется в экземпляр Singleton. Этот метод значительно снижает накладные расходы при вызове синхронизированного метода каждый раз.


Ссылки:

Книга Head First Design Patterns (настоятельно рекомендуется)
https://en.wikipedia.org/wiki/Singleton_pattern

Пожалуйста, напишите комментарии, если вы обнаружите что-то неправильное, или вы хотите поделиться дополнительной информацией по обсуждаемой теме

Рекомендуемые посты:

Синглтон Дизайн Шаблон | Реализация

0.00 (0%) 0 votes