Анимация
JavaScript


Главная  Библионтека 

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

Таблица 6.1. Стратегии класса SingletonHolder

Стратегия Шаблонный класс

Комментарии

Creation

Lifetime

ThreadingModel

CreateusmgNew

CreateusingMalloc

CreateStatic Defaul tL ifeTime

PhoenixSingleton

Si ngletonwi thLongevi ty

NoDestroy SingleThreaded Cl ass LevelLockable

Создает объект с помощью оператора new и конструктора по умолчанию

Создает объект с помощью функции

std: : mall ос и конструктора по умолчанию

Создает объект в статической памяти

Управляет продолжительностью жизни объекта в соответствии с правилами языка С++. Для выполнения задания вызывает функцию atexit

Выполняет то же самое, что и класс DefaultLifetiте, но допускает воссоздание объекта класса Singleton

Задает продолжительность жизни объекта класса Singleton. Предполагается, что в пространстве имен существует функция GetLongevity, которая, будучи вызванной с параметром plnstance , возвращает продолжительность жизни синглтона

Не допускает уничтожения объекта класса Singleton

Детали описаны в приложении

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

6.11. Работа с классом SingletonHodler

Шаблонный класс SingletonHolder не требует от приложения специфических функциональных возможностей. Он просто предоставляет специальные средства для работы с синглтонами в других классах - в нашем коде они обозначены буквой т. Класс т мы будем называть клиентским (client class).

В клиентском классе следует предусмотреть все меры для предотврашенйя непреднамеренного создания и уничтожения объектов: конструктор по умолчанию, конструктор копирования, оператор присваивания, деструктор и оператор взятия адреса должны быть закрытыми.

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

Проектные решения, касающиеся работы со специальной реализацией класса Singleton, отражаются в определении типа, как показано ниже. Передавая признаки и



опции при вызове некоторой функции, вы передаете их определению типа, выбирая соответствующее поведение объектов, class А { ... }

typedef singletonHolder<A, CreateUsingNew> singleA;

Теперь можно использовать функцию SingleA::lnstance()

Описать синглтон, возвращающий объект производного класса, довольно просто. Для этого достаточно внести изменения в класс стратегии Creator, class А { ... };

class Derived : public A { ... };

template <class T> struct MyCreator : public CreateUsingNew<T>

static T* CreateO {

return new Derived;

typedef singletonHolder<A, staticAllocator, MyCreator> SingleA;

Кроме того, можно задать параметры конструктора, использовать другую стратегию распределения памяти или настроить класс Singleton на каждую отдельную стратегию. Это позволяет точно настроить класс Singleton, сохранив все его функциональные возможности, предусмотренные по умолчанию.

Класс стратегии Si ngl etonwi thLongevi ty полагается на определение функции GetLongevi ty, находящейся в пространстве имен. Ее определение может выглядеть следующим образом.

inline unsigned int GetLongevity(А*) { return 5; }

Это нужно, только если вы используете класс Si ngl ewi thLongevi ty в определении типа SingleA.

Наши экспериментальные реализации испытывались на задаче KDL. Теперь она решается с помошью шаблонного класса Singleton. Разумеется, эти определения должны находиться в соответствующих заголовочных файлах.

class Keyboardlmpl {...}; class Displaylmpl { ... }; class Loglmpl {...};

inline unsigned int GetLongevity(Keyboardlmpl*) { return 1; } inline unsigned int GetLongevity(Displaylmpl*) { return 1; } Объекты класс Log живут дольше

inline unsigned int GetLongevity(Loglmpl*) { return 2; }

typedef SingletonHolder<Keyboardimpl, SingletonwithLongevity> Keyboard; typedef SingletonHolder<DisplayImpl, SingletonwithLongevity> Display; typedef Sing!etonHolder<Loglmpl, SingletonwithLongevity> Log;

Учитывая сложность задачи, описанное решение является достаточно простым и очевидным.

6.12. Резюме

в начале главы была описана наиболее популярная реализация класса Singleton на языке С++. Предотвратить тиражирование синглтонов довольно просто, поскольку



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

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

В главе рассмотрены четыре основные вариации на эту тему: синглтон, управляемый компилятором, феникс, синглтон с заданной продолжительностью жизни и бессмертный синглтон. У каждого из них есть свои преимущества и недостатки.

Шаблон проектирования Singleton тесно связан с моделями потоков. Шаблон Double-Checking Locking позволяет создать синглтоны, гарантирующие безопасную работу потоков.

В заключении перечислены и классифицированы основные стратегии и выполнена соответствующая декомпозиция класса singleton. В классе singleton выделены три основные стратегии: Creation, Lifetime и ThreadingModel. Эти стратегии сопряжены в определении класса SingletonHolder с четырьмя параметрами (клиентский тип плюс три стратегии), которые покрывают все возможные комбинации проектных рещений.

6.13. Краткое описание шаблонного класса SingletonHolder

• Определение класса SingletonHolder имеет следующий вид.

template < class т,

template <class> class CreationPolicy = CreateusingNew, template <class> class LifetimePlicy = DefaultLifetime, template <class> class ThreadingModel = SingleThreaded

>

class SingletonHolder;

Шаблонный класс SingletonHolder конкретизируется путем передачи клиентского класса в качестве первого шаблонного параметра. Различные проектные варианты выбираются с помощью комбинирования четырех остальных параметров.

class Myclass { ... }; typedef singleton<MyClass, CreateStatio MySingleClass;

Нужно определить конструктор по умолчанию или использовать для создания синглтона класс, отличающийся от стратегии Creator.

Готовые реализации трех основных стратегий описаны в табл. 6.1. При необходимости к ним можно добавить свои собственные классы стратегий, ориентированные на новые офаничения.



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