Абстрактная фабрика — порождающий шаблон проектирования, позволяющий изменять поведение системы, варьируя создаваемыми объектами, при этом сохраняя интерфейсы. Он позволяет создавать целые группы взаимосвязанных объектов, которые, будучи созданными одной фабрикой, реализуют общее поведение. Шаблон реализуется созданием абстрактного класса Factory, который представляет собой интерфейс для создания компонентов системы (например, для оконного интерфейса он может создавать окна и кнопки). Затем пишутся наследники от него классы, реализующие этот интерфейс.
Сам код:
#ifndef FACTORY_H #define FACTORY_H #include <QString> #include <QHash> #include <QMap> #include <QDebug> template <class Base> class AbstractCreator { public: AbstractCreator() {} virtual ~AbstractCreator(){} virtual Base* create()= 0; Base * instance=0; }; template <class C, class Base> class Creator : public AbstractCreator<Base> { public: Creator() { } virtual ~Creator() {} Base * create() { this->instance= new C(); return this->instance; } }; template <class Base, class IdType> class Factory { protected: typedef AbstractCreator<Base> AbstractFactory; typedef std::map<IdType, AbstractFactory*> FactoryMap; public: Factory() {} virtual ~Factory() {} template <class C> void add(const IdType & id) { registerClass(id, new Creator<C, Base>()); } Base * create(const IdType & id) const { typename FactoryMap::const_iterator it = _factory.find(id); if (it != _factory.end()) return it->second->create(); } Base * getInstance(const IdType & id) const { typename FactoryMap::const_iterator it = _factory.find(id); if (it != _factory.end()) { if (it->second->instance!=0) return it->second->instance; return it->second->create(); } } 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; } private: Factory(const Factory&); Factory& operator = (const Factory&); FactoryMap _factory; }; #endif // FACTORY_H
Теперь применение:
Где-нибудь в заголовочном файле:
class BaseCL {// базовый класс public: virtual ~BaseCL() {} }; class Foo : public BaseCL // производные { public: int i=0; void msg() { qDebug()<<"Foo"; } }; typedef Factory<BaseCL, QString> TypeFactory; // Фабрика с базовым классом BaseCL и идентификаторами типа QString
Применение:
TypeFactory myfactory; myfactory.add<Foo>("FOO"); //-- добавляем класс в фабрику Foo *p = dynamic_cast<Foo *>(myfactory.create("FOO")); //-- создаем класс по идентификатору и приводим к типу Foo p->msg(); //-- вызываем функцию вывода сообщения
1 comment
Base * create(const IdType & id) const:
Base * getInstance(const IdType & id) const:
warning: control reaches end of non-void function [-Wreturn-type]
}