📜 ⬆️ ⬇️

Yet another factory

In the current project, it has often become necessary to construct sets of various objects for some identifiers. One factory was written for some set, another. Then the understanding came that we are doing the same thing and we need some kind of repeatable solution.
The project is based on Qt, which, as you know, has developed mechanisms for working with metadata. Nevertheless, the construction of objects through QMetaObject did not satisfy us for two reasons: firstly, the constructed objects must be QObjects, and secondly, in the design, we get a pointer to a QObject, which one way or another will have to be transformed, which is purely aesthetically ugly.

After analyzing the range of tasks, we came to the conclusion that we want to have a static factory in the base classes of some sets of heirs. Those. write something like this:

BaseClass * instance = BaseClass::factory()->build("derived_name"); 

')
At the same time, we do not want to write a lot of uniform service code every time. Yes, we are lazy.
And of course, we don’t want the factory or base class to know about all the heirs.

Having a little thought, we invented a factory solving a wide range of our tasks.

Factory

To begin with, I'll give the factory code, since it turned out to be compact:
 template<class Base> class UnifiedFactory { public: UnifiedFactory(){} ~UnifiedFactory(){qDeleteAll(m_builders);} template<class T> void registerClass(const QString& name) { delete m_builders.value(name); m_builders.insert(name, new Builder<T>()); } Base * build(const QString& name) const { BaseBuilder * builder = m_builders.value(name); if(builder) return builder->build(); return 0; } private: class BaseBuilder { public: virtual Base * build() const = 0; }; template<class T> class Builder : public BaseBuilder { public: virtual Base * build() const { return new T(); } }; typedef QHash<QString, BaseBuilder*> Builders; Builders m_builders; }; 


As you can see, this template factory is able to construct only objects with a common base class .
, template registerClass(const QString& name), T - .
, -, BaseBuilder build() (!) Builder, .
- . , . , , .
.

, - .



#define UNIFIED_FACTORY(BaseType) \ static UnifiedFactory<BaseType>* factory() \ { \ static UnifiedFactory<BaseType> s_factory; \ return &s_factory; \ } \ template<class T> \ class AutoRegistrer \ { \ public: \ AutoRegistrer(const QString& name){factory()->registerClass<T>(name);} \ }; \ #define UF_REGISTER_DERIVED_NAMED(type, name) \ static const type::AutoRegistrer<type> type##Registrator(name); #define UF_REGISTER_DERIVED(type) UF_REGISTER_DERIVED_NAMED(type, #type)


, - template class AutoRegistrer, - - .

UF_REGISTER_DERIVED_NAMED , AutoRegistrer.
,


, :
class Base { publi: UNIFIED_FACTORY(Base) }; class Derived1 : public Base {...} UF_REGISTER_DERIVED(Derived1) class Derived2 : public Base {...} UF_REGISTER_DERIVED(Derived2) .... Base * instance = Base::factory()->build("Derived1")



, , . - . , .
, Qt- , STL- .
, . , .

PS: ?
.
, template registerClass(const QString& name), T - .
, -, BaseBuilder
build() (!) Builder, .
- . , . , , .
.

, - .



#define UNIFIED_FACTORY(BaseType) \ static UnifiedFactory<BaseType>* factory() \ { \ static UnifiedFactory<BaseType> s_factory; \ return &s_factory; \ } \ template<class T> \ class AutoRegistrer \ { \ public: \ AutoRegistrer(const QString& name){factory()->registerClass<T>(name);} \ }; \ #define UF_REGISTER_DERIVED_NAMED(type, name) \ static const type::AutoRegistrer<type> type##Registrator(name); #define UF_REGISTER_DERIVED(type) UF_REGISTER_DERIVED_NAMED(type, #type)


, - template class AutoRegistrer, - - .

UF_REGISTER_DERIVED_NAMED , AutoRegistrer.
,


, :
class Base { publi: UNIFIED_FACTORY(Base) }; class Derived1 : public Base {...} UF_REGISTER_DERIVED(Derived1) class Derived2 : public Base {...} UF_REGISTER_DERIVED(Derived2) .... Base * instance = Base::factory()->build("Derived1")



, , . - . , .
, Qt- , STL- .
, . , .

PS: ?
 . 
, template registerClass(const QString& name), T - .
, -, BaseBuilder
build() (!) Builder, .
- . , . , , .
.

, - .



#define UNIFIED_FACTORY(BaseType) \ static UnifiedFactory<BaseType>* factory() \ { \ static UnifiedFactory<BaseType> s_factory; \ return &s_factory; \ } \ template<class T> \ class AutoRegistrer \ { \ public: \ AutoRegistrer(const QString& name){factory()->registerClass<T>(name);} \ }; \ #define UF_REGISTER_DERIVED_NAMED(type, name) \ static const type::AutoRegistrer<type> type##Registrator(name); #define UF_REGISTER_DERIVED(type) UF_REGISTER_DERIVED_NAMED(type, #type)

, - template class AutoRegistrer, - - .

UF_REGISTER_DERIVED_NAMED , AutoRegistrer.
,


, :
class Base { publi: UNIFIED_FACTORY(Base) }; class Derived1 : public Base {...} UF_REGISTER_DERIVED(Derived1) class Derived2 : public Base {...} UF_REGISTER_DERIVED(Derived2) .... Base * instance = Base::factory()->build("Derived1")



, , . - . , .
, Qt- , STL- .
, . , .

PS: ?
.
, template registerClass(const QString& name), T - .
, -, BaseBuilder
build() (!) Builder, .
- . , . , , .
.

, - .



#define UNIFIED_FACTORY(BaseType) \ static UnifiedFactory<BaseType>* factory() \ { \ static UnifiedFactory<BaseType> s_factory; \ return &s_factory; \ } \ template<class T> \ class AutoRegistrer \ { \ public: \ AutoRegistrer(const QString& name){factory()->registerClass<T>(name);} \ }; \ #define UF_REGISTER_DERIVED_NAMED(type, name) \ static const type::AutoRegistrer<type> type##Registrator(name); #define UF_REGISTER_DERIVED(type) UF_REGISTER_DERIVED_NAMED(type, #type)

, - template class AutoRegistrer, - - .

UF_REGISTER_DERIVED_NAMED , AutoRegistrer.
,


, :
class Base { publi: UNIFIED_FACTORY(Base) }; class Derived1 : public Base {...} UF_REGISTER_DERIVED(Derived1) class Derived2 : public Base {...} UF_REGISTER_DERIVED(Derived2) .... Base * instance = Base::factory()->build("Derived1")



, , . - . , .
, Qt- , STL- .
, . , .

PS: ?
.
, template registerClass(const QString& name), T - .
, -, BaseBuilder
build() (!) Builder, .
- . , . , , .
.

, - .



#define UNIFIED_FACTORY(BaseType) \ static UnifiedFactory<BaseType>* factory() \ { \ static UnifiedFactory<BaseType> s_factory; \ return &s_factory; \ } \ template<class T> \ class AutoRegistrer \ { \ public: \ AutoRegistrer(const QString& name){factory()->registerClass<T>(name);} \ }; \ #define UF_REGISTER_DERIVED_NAMED(type, name) \ static const type::AutoRegistrer<type> type##Registrator(name); #define UF_REGISTER_DERIVED(type) UF_REGISTER_DERIVED_NAMED(type, #type)


, - template class AutoRegistrer, - - .

UF_REGISTER_DERIVED_NAMED , AutoRegistrer.
,


, :
class Base { publi: UNIFIED_FACTORY(Base) }; class Derived1 : public Base {...} UF_REGISTER_DERIVED(Derived1) class Derived2 : public Base {...} UF_REGISTER_DERIVED(Derived2) .... Base * instance = Base::factory()->build("Derived1")



, , . - . , .
, Qt- , STL- .
, . , .

PS: ?
.
, template registerClass(const QString& name), T - .
, -, BaseBuilder
build() (!) Builder, .
- . , . , , .
.

, - .



#define UNIFIED_FACTORY(BaseType) \ static UnifiedFactory<BaseType>* factory() \ { \ static UnifiedFactory<BaseType> s_factory; \ return &s_factory; \ } \ template<class T> \ class AutoRegistrer \ { \ public: \ AutoRegistrer(const QString& name){factory()->registerClass<T>(name);} \ }; \ #define UF_REGISTER_DERIVED_NAMED(type, name) \ static const type::AutoRegistrer<type> type##Registrator(name); #define UF_REGISTER_DERIVED(type) UF_REGISTER_DERIVED_NAMED(type, #type)


, - template class AutoRegistrer, - - .

UF_REGISTER_DERIVED_NAMED , AutoRegistrer.
,


, :
class Base { publi: UNIFIED_FACTORY(Base) }; class Derived1 : public Base {...} UF_REGISTER_DERIVED(Derived1) class Derived2 : public Base {...} UF_REGISTER_DERIVED(Derived2) .... Base * instance = Base::factory()->build("Derived1")



, , . - . , .
, Qt- , STL- .
, . , .

PS: ?
 . 
, template registerClass(const QString& name), T - .
, -, BaseBuilder
build() (!) Builder, .
- . , . , , .
.

, - .



#define UNIFIED_FACTORY(BaseType) \ static UnifiedFactory<BaseType>* factory() \ { \ static UnifiedFactory<BaseType> s_factory; \ return &s_factory; \ } \ template<class T> \ class AutoRegistrer \ { \ public: \ AutoRegistrer(const QString& name){factory()->registerClass<T>(name);} \ }; \ #define UF_REGISTER_DERIVED_NAMED(type, name) \ static const type::AutoRegistrer<type> type##Registrator(name); #define UF_REGISTER_DERIVED(type) UF_REGISTER_DERIVED_NAMED(type, #type)


, - template class AutoRegistrer, - - .

UF_REGISTER_DERIVED_NAMED , AutoRegistrer.
,


, :
class Base { publi: UNIFIED_FACTORY(Base) }; class Derived1 : public Base {...} UF_REGISTER_DERIVED(Derived1) class Derived2 : public Base {...} UF_REGISTER_DERIVED(Derived2) .... Base * instance = Base::factory()->build("Derived1")


, , . - . , .
, Qt- , STL- .
, . , .

PS: ?
.
, template registerClass(const QString& name), T - .
, -, BaseBuilder
build() (!) Builder, .
- . , . , , .
.

, - .



#define UNIFIED_FACTORY(BaseType) \ static UnifiedFactory<BaseType>* factory() \ { \ static UnifiedFactory<BaseType> s_factory; \ return &s_factory; \ } \ template<class T> \ class AutoRegistrer \ { \ public: \ AutoRegistrer(const QString& name){factory()->registerClass<T>(name);} \ }; \ #define UF_REGISTER_DERIVED_NAMED(type, name) \ static const type::AutoRegistrer<type> type##Registrator(name); #define UF_REGISTER_DERIVED(type) UF_REGISTER_DERIVED_NAMED(type, #type)


, - template class AutoRegistrer, - - .

UF_REGISTER_DERIVED_NAMED , AutoRegistrer.
,


, :
class Base { publi: UNIFIED_FACTORY(Base) }; class Derived1 : public Base {...} UF_REGISTER_DERIVED(Derived1) class Derived2 : public Base {...} UF_REGISTER_DERIVED(Derived2) .... Base * instance = Base::factory()->build("Derived1")


, , . - . , .
, Qt- , STL- .
, . , .

PS: ?
.
, template registerClass(const QString& name), T - .
, -, BaseBuilder
build() (!) Builder, .
- . , . , , .
.

, - .



#define UNIFIED_FACTORY(BaseType) \ static UnifiedFactory<BaseType>* factory() \ { \ static UnifiedFactory<BaseType> s_factory; \ return &s_factory; \ } \ template<class T> \ class AutoRegistrer \ { \ public: \ AutoRegistrer(const QString& name){factory()->registerClass<T>(name);} \ }; \ #define UF_REGISTER_DERIVED_NAMED(type, name) \ static const type::AutoRegistrer<type> type##Registrator(name); #define UF_REGISTER_DERIVED(type) UF_REGISTER_DERIVED_NAMED(type, #type)


, - template class AutoRegistrer, - - .

UF_REGISTER_DERIVED_NAMED , AutoRegistrer.
,


, :
class Base { publi: UNIFIED_FACTORY(Base) }; class Derived1 : public Base {...} UF_REGISTER_DERIVED(Derived1) class Derived2 : public Base {...} UF_REGISTER_DERIVED(Derived2) .... Base * instance = Base::factory()->build("Derived1")



, , . - . , .
, Qt- , STL- .
, . , .

PS: ?
.
, template registerClass(const QString& name), T - .
, -, BaseBuilder
build() (!) Builder, .
- . , . , , .
.

, - .



#define UNIFIED_FACTORY(BaseType) \ static UnifiedFactory<BaseType>* factory() \ { \ static UnifiedFactory<BaseType> s_factory; \ return &s_factory; \ } \ template<class T> \ class AutoRegistrer \ { \ public: \ AutoRegistrer(const QString& name){factory()->registerClass<T>(name);} \ }; \ #define UF_REGISTER_DERIVED_NAMED(type, name) \ static const type::AutoRegistrer<type> type##Registrator(name); #define UF_REGISTER_DERIVED(type) UF_REGISTER_DERIVED_NAMED(type, #type)


, - template class AutoRegistrer, - - .

UF_REGISTER_DERIVED_NAMED , AutoRegistrer.
,


, :
class Base { publi: UNIFIED_FACTORY(Base) }; class Derived1 : public Base {...} UF_REGISTER_DERIVED(Derived1) class Derived2 : public Base {...} UF_REGISTER_DERIVED(Derived2) .... Base * instance = Base::factory()->build("Derived1")



, , . - . , .
, Qt- , STL- .
, . , .

PS: ?

.
, template registerClass(const QString& name), T - .
, -, BaseBuilder
build() (!) Builder, .
- . , . , , .
.

, - .



#define UNIFIED_FACTORY(BaseType) \ static UnifiedFactory<BaseType>* factory() \ { \ static UnifiedFactory<BaseType> s_factory; \ return &s_factory; \ } \ template<class T> \ class AutoRegistrer \ { \ public: \ AutoRegistrer(const QString& name){factory()->registerClass<T>(name);} \ }; \ #define UF_REGISTER_DERIVED_NAMED(type, name) \ static const type::AutoRegistrer<type> type##Registrator(name); #define UF_REGISTER_DERIVED(type) UF_REGISTER_DERIVED_NAMED(type, #type)


, - template class AutoRegistrer, - - .

UF_REGISTER_DERIVED_NAMED , AutoRegistrer.
,


, :
class Base { publi: UNIFIED_FACTORY(Base) }; class Derived1 : public Base {...} UF_REGISTER_DERIVED(Derived1) class Derived2 : public Base {...} UF_REGISTER_DERIVED(Derived2) .... Base * instance = Base::factory()->build("Derived1")



, , . - . , .
, Qt- , STL- .
, . , .

PS: ?

.
, template registerClass(const QString& name), T - .
, -, BaseBuilder
build() (!) Builder, .
- . , . , , .
.

, - .



#define UNIFIED_FACTORY(BaseType) \ static UnifiedFactory<BaseType>* factory() \ { \ static UnifiedFactory<BaseType> s_factory; \ return &s_factory; \ } \ template<class T> \ class AutoRegistrer \ { \ public: \ AutoRegistrer(const QString& name){factory()->registerClass<T>(name);} \ }; \ #define UF_REGISTER_DERIVED_NAMED(type, name) \ static const type::AutoRegistrer<type> type##Registrator(name); #define UF_REGISTER_DERIVED(type) UF_REGISTER_DERIVED_NAMED(type, #type)


, - template class AutoRegistrer, - - .

UF_REGISTER_DERIVED_NAMED , AutoRegistrer.
,


, :
class Base { publi: UNIFIED_FACTORY(Base) }; class Derived1 : public Base {...} UF_REGISTER_DERIVED(Derived1) class Derived2 : public Base {...} UF_REGISTER_DERIVED(Derived2) .... Base * instance = Base::factory()->build("Derived1")



, , . - . , .
, Qt- , STL- .
, . , .

PS: ?

Source: https://habr.com/ru/post/147942/


All Articles