IT Notes

Паттерн Singleton

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

Без условия уникальности Синглтон является обычной глобальной переменной с учетом вытекающих плюсов и минусов (которых большинство). Поэтому перед тем, как использовать этот паттерн, убедитесь, что он действительно подходит. Объект, который предполагается реализовать в виде Синглтона должен быть по-настоящему единственным на уровне системы.

Пример реализация паттерна Singleton на C++

Технически реализовать объект-Синглтон и использовать его в приложении довольно просто (что подкупает):

#include <iostream>

class MySingleton {
public:
    // Функция-член для доступа к единственному экземпляру
    static MySingleton* getInstance() {
        static MySingleton instance;
        return &instance;
    }

    // Наполняем полезным функционалом, как и любой другой класс
    void test() {
        std::cout << "Singleton test" << std::endl;
    }

private:
    // Объявляем конструктор закрытым, чтобы нельзя было
    // создавать экземпляры класса извне
    MySingleton() { }
};

int main() {
    // Используем Синглтон
    MySingleton::getInstance()->test();

    // А это работать не будет, поскольку конструктор - закрытый
    // MySingleton singleton;

    return 0;
}

При желании объект-Синглтон можно адаптировать к многопоточной среде выполнения с помощью мьютексов.

Всегда думайте перед созданием Синглтона

Заманчиво иметь некий объект, доступный в любой точке программы. Но это нарушает многие принципы создания хорошего кода. Поэтому не спешите добавлять Синглтоны, которые усложняют логику программы и вносят лишние зависимости.

Рассмотрим пример. Может показаться хорошей идеей создать класс для управления настройками приложения в виде Синглтона. Тогда все компоненты приложения смогут видеть необходимые опции и легко их использовать. С одной стороны, идея кажется довольно неплохой. Конфигурация приложения действительно может быть представлена уникальной сущностью. А свободный доступ к Синглтону упростит использование конфигурации.

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

К тому же, паттерн Синглтон усложняет использование полиморфизма и других прелестей ООП, которые могут понадобится, когда уже минимальным рефакторингом обойтись не удастся.

Хотя есть и вполне безобидные применения Синглтонов. Например, при реализации другого паттерна: Абстрактная Фабрика.

Также использование Синглтона оправдано для представления физически уникальных ресурсов компьютера. Например, систему слежения за подключением/отключением USB-устройств уместно реализовать в виде Синглтона.

Понравилась статья?
Не забудь поделиться ей с друзьями!

Похожие публикации

Комментарии

Хорошая статья, но возникло одно замечание:

MySingleton &ref = *(MySingleton::getInstance());

MySingleton doubleton(ref);

Обычно дополнительно объявляют оператор присваивания и конструктор копирования в private секции.

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

Спасибо за полезный комментарий :)

Xoanis:

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

Довольно странное поведение. В моей практике наблюдалось нечто подобное только из-за ошибки. Когда в разных подпроектах линковались разные версии одной и той же dll-библиотеки (одна в Release, а другая в Debug).

RSS RSS-рассылка

Популярное

Дешевый хостинг