Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: ТОП 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; просмотров: 128; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 216.73.216.41 (0.01 с.) |