Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Class fooCreator : public abstractFooCreatorСодержание книги
Поиск на нашем сайте
{ public: virtual Foo * create() const { return new C(); } }; Теперь уже можно написать шаблонный метод для добавления класса в фабрику. Единственное, что нам нужно уже выбрать контейнер для хранения наших creator'ов. Выбором может быть std::map.
typedef std::map<std::string, abstractFooCreator*> FactoryMap; FactoryMap _factory; template <class C> void add(const std::string & id) { typename FactoryMap::iterator it = _factory.find(id); if (it == _factory.end()) _factory[id] = new fooCreator<C>(); } Появился первый рабочий вариант фабрики, в которую можно добавлять классы, поддерживающие интерфейс Foo.
Foo * create(const std::string & id) const { typename FactoryMap::iterator it = _factory.find(id); if (it!= _factory.end()) return it->second->create(); return 0; } Соберем весь код, чтобы увидеть полную картину.
Class abstractFooCreator { Public: virtual fooCreator() {} virtual Foo * create() const = 0; }; template <class C> Class fooCreator: public abstractFooCreator { public:
virtual Foo * create() const { return new C(); } }; С lass FooFactory { protected: typedef std::map<std::string, abstractFooCreator*> FactoryMap; FactoryMap _factory; public: FooFactory(); ~virtual FooFactory(); template <class C> void add(const std::string & id) { typename FactoryMap::iterator it = _factory.find(id); if (it == _factory.end()) _factory[id] = new fooCreator<C>(); } Foo * create(const std::string & id) { typename FactoryMap::iterator it = _factory.find(id); if (it!= _factory.end()) return it->second->create(); return NULL; } }; Пример, как данную фабрику использовать. Добавление классов в фабрику: FooFactory factory; factory.add<MyFoo>("MyFoo"); factory.add<MyFoo2>("MyFoo2"); factory.add<ImprovedFoo>("ImprovedFoo"); Создание объекта с помощью фабрики: Foo * p = factory.create("MyFoo2"); Вот так просто с помощью фабрики можно управлять созданием объектов, поддерживающих единый интерфейс.
Создание шаблонной фабрики
Ну, а теперь создадим, на основе этого конкретного примера, вполне конкретный паттерн.
Что нужно нашей фабрике, чтобы удовлетворять наши возможности? Конечно, это задание типа идентификатора, который можем быть как и enum'ом, так и std::string или любым другим типом подходящим для идентификатора. Второе — это собственно тип объектов, которые мы будем создавать, роль которого в примере выше исполнял класс Foo.
template <class Base, class IdType> Class ObjectFactory { public: ObjectFactory() {} virtual ~ObjectFactory(); template <class C> void add(const IdType & id); Base * create() const; };
Вот так будет выглядеть наша шаблонная фабрика. Приступим к ее реализации. Как и в примере с Foo, нам нужно решить проблему создания объектов конкретного типа. То есть нам нужен абстрактный класс, у которого есть метод для создания объекта типа Base, и конкретный creator класс, который наследует этот абстрактный класс и реализует этот метод, используя шаблонный параметр.
template <class Base> Class AbstractCreator { public: AbstractCreator() {} virtual ~AbstractCreator(){} virtual Base* create() const = 0; }; template <class C, class Base> class Creator: public AbstractCreator<Base> { public: Creator() { } virtual ~Creator() {} Base * create() const { return new C(); } }; Ну, а теперь нужно лишь использовать эти классы в нашей фабрике.
template <class Base, class IdType> Class ObjectFactory { protected: typedef AbstractCreator<Base> AbstractFactory; typedef std::map<IdType, AbstractFactory*> FactoryMap; FactoryMap _factory; public: ObjectFactory() {} virtual ~ObjectFactory(); template <class C> void add(const IdType & id) { registerClass(id, new Creator<C, Base>()); } protected: void registerClass(const IdType & id, AbstractFactory * p) { typename FactoryMap::iterator it = _factory.find(id); if (it == _factory.end()) _factory[id] = p; else delete p; } };
Что существенного добавилось по сравнению с примером Foo? Конечно же это метод registerClass, который в качестве параметра принимает объект типа AbstractFactory, который, в свою очередь, умеет создавать объекты того класса, который мы указываем как шаблонный параметр для метода add.
Добавляем возможность задания поведения фабрики
Чтобы уметь задавать поведение фабрики нам нужно использовать другой паттерн проектирования — Стратегия, так же известного под именем Политика. Данный паттерн очень хорошо освещен в книге А. Александреску «Современное проектирование на С++».
Помимо собственно самих функций, реализующих поведение, для класса политики нужны так же и тип интерфейса, который реализует фабрика и тип идентификатора для которого произошла ошибка и который передается во все методы. Теперь встроим нашу политику в фабрику. Это можно сделать несколькими способами — просто наследоваться от класса политики, или использовать класс политики как атрибут фабрики. В обоих случаях единственная проблема в том, каким образом из класса фабрики задавать шаблонные параметры для класса политики. В этом нам поможет замечательная особенность С++ — шаблонные параметры. Когда при объявлении класса фабрики указываем что мы хотим передать в качестве параметра не просто какой-то класс, а шаблонный класс. Но все это очень трудно.
|
||||
Последнее изменение этой страницы: 2021-11-27; просмотров: 58; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.118.162.166 (0.006 с.) |