Анимация
JavaScript
|
Главная Библионтека Реализация шаблона Singleton Шаблон проектирования Singleton (Gamma et al, 1995) представляет собой уникальную комбинацию простого описания и сложной реализации. Об этом свидетельствуют многочисленные книги и журнальные публикации (например, Vlissides, 1996, 1998). Описание шаблона Singleton в книге Gamma et al. (1995) весьма просто: "Шаблон гарантирует, что класс имеет только один экземпляр и обеспечивает глобальный доступ к нему". Синглтон - это улучшенный вариант глобальной переменной. Новшество заключается в том, что второй объект типа Singleton создать нельзя. Следовательно, синглтоны можно использовать в приложениях при моделировании типов, имеющих только один экземпляр, таких как Keyboard, Display, PrintManager и Systemclock. Создавать вторые экземпляры таких классов соверщенно неестественно и, кроме того, опасно. Глобальный доступ имеет скрытые побочные последствия - с точки зрения клиента объект класса singleton владеет самим собой. Для создания объекта класса Singleton клиент ничего не должен делать. Следовательно, объект класса Singltone сам создает и разрушает себя. Управление продолжительностью жизни синглтона представляет собой головоломную задачу. В этой главе обсуждаются наиболее важные вопросы, связанные с проектированием и реализацией разных вариантов класса Singleton в языке С++. • Свойства, которые отличают синглтон от обычной глобальной переменной. • Основные идиомы языка С++ для поддержки синглтонов. • Обеспечение уникальности синглтона. • Уничтожение синглтона и распознавание доступа после уничтожения. • Усовершенствованное управление продолжительностью жизни объекта класса Singltone. • Многопоточность. Мы опишем способы решения перечисленных выше проблем, а затем применим их для реализации обобщенного шаблонного класса SingletonHolder. "Оптимальной" реализации шаблона проектирования Singleton не существует. В зависимости от конкретной задачи наилучшими оказываются различные реализации, включая машинно-зависимые. Подход, описанный в этой главе, предназначен для разработки семейства реализаций на основе обобщенного скелета класса в духе проектирования на основе стратегий (глава 1). Класс SingletonHand оставляет также возможности для его расширения и настройки. В конце этой главы мы разработаем шаблонный класс SingletonHolder, способный генерировать много синглтонов разного типа. Класс SingletonHolder предостав- ляет профаммисту возможности для детального управления распределением памяти при создании и уничтожении синглтонов при условии, что это не создает опасности для потоков. Кроме того, класс определяет, что делать, если пользователь попытался обратиться к уже разрушенному синглтону. Шаблонный класс singletonHolder предоставляет программисту функциональные возможности, выходящие за рамки обычных типов, определенных пользователем. 6.1. Статические данные + статические функции != синглтон На первый взгляд кажется, что для создания класса singleton нужны лишь статические функции-члены и переменные-члены. class Font {...}; class Printerport { ... }; class PrintJob { ... } class MyOnlyPrinter { public: static void AddPrintJobCPrintJobA newjob) { ifCprintQueue .emptyC) && printingPort .availableC)) printingPort . sendCnewjob.DataO); else { printQueue .pushCnewjob); . private: все данные являются статическими static std::queue<PrintJob> printQueue ; static printerport printingPort ; static Font defaultFont ; PrintJob somePrintJobCMyDocument.txt"); MyOnlyPrinter::AddPrintJobCsomePrintJob); Однако это решение в некоторых ситуациях имеет много недостатков. Основная проблема заключается в том, что статические функции не могут быть виртуальными, что не позволяет изменять поведение объекта при открытии кода класса MyOnlyPrinter. Кроме того, инициализация и удаление объекта затрудняются. В классе MyOnlyPrinter нет конкретных точек, в которых инициализируются и удаляются данные, хотя эти задачи могут быть нетривиальными - например, переменная-член default-Font, может зависеть от скорости обмена данными порта, поведение которого описывается переменной printingPort . Таким образом, реализация синглтонов сводится к созданию и управлению уникальным объектом, при этом создавать другие объекты такого типа запрещено. На самом деле этот код иллюстрирует шаблон проектирования Monostate (Ball and Crawford, 1998). 6.2. Основные идиомы языка С++для поддержки синглтонов Чаще всего синглтоны создаются с помощью вариаций следующей идиомы. Заголовочный файл Singleton.h class Singleton public: static Singleton* instanceC) Единственная точка доступа { if (!pinstance ) plnstance = new singleton; return pinstance ; ... операции ... private: SingletonC); предотвращает создание нового объекта класса Singleton Singleton(const Sing1eton&); предотвращает создание копии объекта класса singleton static Sing1eton&* plnstance ; Единственный экземпляр Файл реализации Singleton.cpp Singleton* singleton::pinstance = 0; Поскольку все конструкторы закрыты, код пользователя не может создать объект класса Singleton. Однако класс содержит функции-члены, в частности, функцию Instance, которые позволяют создавать объекты. Следовательно, требование уникальности объекта класса Singleton накладывается на этапе компиляции. В этом и заключается суть реализации щаблона проектирования Si ngl eton в языке С++. Если объект класса Singleton никогда не используется (в профамме нет вызовов функции Instance), он не создается. Для осуществления такой оптимизации в начале функции Instance выполняется дополнительная проверка (обычно весьма несложная). Преимущество такого подхода становится значительным, если объект класса singleton фебует для своего создания больших затрат и в то же время редко используется. Есть большое искушение упростить класс, заменив указатель plnstance в предыдущем примере полноценным объектом класса singleton. Заголовочный файл Singleton.h class Singleton public: static Singleton* instanceC) Единственная точка доступа { return &instance ; int DoSomethingO; private: static Singleton instance.; Файл реализации singleton.cpp si ngleton singleton::instance ; Это неудачное решение. Несмотря на то что переменная instance является статическим членом класса Singleton (как и указатель plnstance в предыдущем при- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 [ 45 ] 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |