Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Class Singleton; // опережающее объявление
Class SingletonDestroyer { private: Singleton* p_instance; public: ~SingletonDestroyer(); void initialize(Singleton* p); }; Class Singleton { private: static Singleton* p_instance; static SingletonDestroyer destroyer; protected: Singleton() { } Singleton(const Singleton&); Singleton& operator=(Singleton&); ~Singleton() { } friend class SingletonDestroyer; public: static Singleton& getInstance(); }; // Singleton.cpp #include "Singleton.h" Singleton * Singleton::p_instance = 0; SingletonDestroyer Singleton::destroyer; SingletonDestroyer::~SingletonDestroyer() { delete p_instance; } void SingletonDestroyer::initialize(Singleton* p) { p_instance = p; } Singleton& Singleton::getInstance() { if(!p_instance) { p_instance = new Singleton(); destroyer.initialize(p_instance); } return *p_instance; } Ключевой особенностью этой реализации является наличие класса SingletonDestroyer, предназначенного для автоматического разрушения объекта Singleton. Класс Singleton имеет статический член SingletonDestroyer, который инициализируется при первом вызове Singleton::getInstance() создаваемым объектом Singleton. При завершении программы этот объект будет автоматически разрушен деструктором SingletonDestroyer (для этого S ingletonDestroye r объявлен другом класса Singleton).
Для предотвращения случайного удаления пользователями объекта класса Singleton, деструктор теперь уже не является общедоступным как ранее. Он объявлен защищенным.
/*Использование нескольких взаимозависимых одиночек
До сих пор предполагалось, что в программе используется один одиночка либо несколько несвязанных между собой. При использовании взаимосвязанных одиночек появляются новые вопросы:
Как гарантировать, что к моменту использования одного одиночки, экземпляр другого зависимого уже создан? Как обеспечить возможность безопасного использования одного одиночки другим при завершении программы? Другими словами, как гарантировать, что в момент разрушения первого одиночки в его деструкторе еще возможно использование второго зависимого одиночки (то есть второй одиночка к этому моменту еще не разрушен)? Управлять порядком создания одиночек относительно просто. Следующий код демонстрирует один из возможных методов.
// Singleton.h Class Singleton1 { private: Singleton1() { } Singleton1(const Singleton1&); Singleton1& operator=(Singleton1&); public: static Singleton1& getInstance() { static Singleton1 instance; return instance; } }; Class Singleton2 { private: Singleton2(Singleton1& instance): s1(instance) { } Singleton2(const Singleton2&); Singleton2& operator=(Singleton2&); Singleton1& s1; public: static Singleton2& getInstance() {
static Singleton2 instance(Singleton1::getInstance()); return instance; } }; // main.cpp #include "Singleton.h" Int main() { Singleton2& s = Singleton2::getInstance(); return 0; } Объект Singleton1 гарантированно инициализируется раньше объекта Singleton2, так как в момент создания объекта Singleton2 происходит вызов Singleton1::getInstance().
Гораздо сложнее управлять временем жизни одиночек. Существует несколько способов это сделать, каждый из них обладает своими достоинствами и недостатками и заслуживают отдельного рассмотрения. Обсуждение этой непростой темы остается за рамками лекции. */ Несмотря на кажущуюся простоту паттерна Singleton (используется всего один класс), его реализация не является тривиальной.
Например, если у нас не однопоточное приложение могу возникнуть гонки потоков. При обращении к Singleton гонки связаны с тем, что если объект еще не был создан и 2 потока одновременно выполнят операцию instance, то может быть создано несколько одиночек.
SimpleClass* SimpleClass::instance() { // 1 if(m_pinstance == 0) // 2 m_pinstance = new SimpleClass; // 3 return m_pinstance; // 4 } // 5 Так, например, первый поток может выполнить проверку условия из второй строки и быть прерван во время выполнения конструктора. Пока первый поток отдыхает, начинается работать второй поток, который выполняет тот же код, но в связи с тем, что первый поток не выполнял инициализации m_pinstance, второй поток также вызывает конструктор SimpleClass и возвращает указатель на созданный объект. После этого может быть активирован первый поток, который заканчивает создание своего экземпляра объекта и повторно инициализирует m_pinstance.
Для решения проблемы гонок можно использовать средства синхронизации потоков (мьютексы), которые в настоящее время включены в стандартную библиотеку.
static SimpleClass* SimpleClass::instance() { static QMutex mutex; if (!m_pinstance) { mutex.lock(); if (!m_pinstance) m_pinstance = new SimpleClass; mutex.unlock(); } return m_pinstance; } С другой стороны, у реализации Singleton, использующей статическую локальную переменную метода instance, состояния гонок потоков возникнуть не может. Это гарантируется стандартом (цитата относится к инициализации локальных статических переменных):
|
|||||
Последнее изменение этой страницы: 2021-11-27; просмотров: 74; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.217.144.32 (0.009 с.) |