-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfactory.h
154 lines (127 loc) · 3.81 KB
/
factory.h
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#ifndef FACTORY_H
#define FACTORY_H
//#define AUTO_PTR 1
#if defined(AUTO_PTR)
#include <memory>
#endif
#include <string>
#include <map>
#include <iostream>
typedef std::string defaultIDKeyType;
// CPP macro implementation
template <class Base>
class BaseFactory {
public:
#if defined(AUTO_PTR)
typedef std::auto_ptr<Base> BasePtr;
#else
typedef Base* BasePtr;
#endif
private:
typedef BasePtr (*BaseCreateFn)();
typedef std::map<defaultIDKeyType, BaseCreateFn> FnRegistry;
FnRegistry registry;
BaseFactory() : registry() {}
BaseFactory(const BaseFactory &); // Not implemented
BaseFactory & operator=(const BaseFactory &); // Not implemented
public:
static BaseFactory & instance()
{
static BaseFactory bf;
return bf;
}
bool RegCreateFn(const defaultIDKeyType &className, BaseCreateFn fn)
{
registry[className] = fn;
return true;
}
BasePtr create(const defaultIDKeyType &className) const
{
BasePtr theObject(0);
typename FnRegistry::const_iterator regEntry = registry.find(className);
if (regEntry != registry.end()) {
theObject = regEntry->second();
}
return theObject;
}
void content() const
{
typename FnRegistry::const_iterator regEntry = registry.begin();
std::cout << "Factory content: " << std::endl;
for ( ; regEntry != registry.end(); ++regEntry) {
std::cout << " * " << regEntry->first << std::endl;
}
}
};
#define REGISTER_CLASS(BASE_CLASS, DERIVED_CLASS) \
namespace \
{ \
BaseFactory<BASE_CLASS>::BasePtr Create##DERIVED_CLASS() \
{ \
return BaseFactory<BASE_CLASS>::BasePtr(new DERIVED_CLASS); \
} \
bool dummy = BaseFactory<BASE_CLASS>::instance().RegCreateFn( \
#DERIVED_CLASS, Create##DERIVED_CLASS); \
} \
// Generic implementation
template <class ManufacturedType, typename ClassIDKey=defaultIDKeyType>
class GenericFactory {
public:
#if defined(AUTO_PTR)
typedef std::auto_ptr<ManufacturedType> BasePtr;
#else
typedef ManufacturedType* BasePtr;
#endif
private:
typedef BasePtr (*BaseCreateFn)();
typedef std::map<ClassIDKey, BaseCreateFn> FnRegistry;
FnRegistry registry;
GenericFactory() : registry() {}
GenericFactory(const GenericFactory&); // Not implemented
GenericFactory &operator=(const GenericFactory&); // Not implemented
public:
static GenericFactory &instance()
{
static GenericFactory<ManufacturedType, ClassIDKey> bf;
return bf;
}
void RegCreateFn(const ClassIDKey & id, BaseCreateFn fn)
{
registry[id] = fn;
}
BasePtr create(const ClassIDKey &className) const
{
BasePtr theObject(0);
typename FnRegistry::const_iterator regEntry = registry.find(className);
if (regEntry != registry.end()) {
theObject = regEntry->second();
}
return theObject;
}
void content() const
{
typename FnRegistry::const_iterator regEntry = registry.begin();
std::cout << "Factory content: " << std::endl;
for ( ; regEntry != registry.end(); ++regEntry) {
std::cout << " * " << regEntry->first << std::endl;
}
}
};
template <class AncestorType,
class ManufacturedType,
typename ClassIDKey=defaultIDKeyType>
class RegisterInFactory {
private:
typedef GenericFactory<AncestorType, ClassIDKey> Factory;
typedef typename Factory::BasePtr BasePtr;
public:
static BasePtr CreateInstance()
{
return BasePtr(new ManufacturedType);
}
explicit RegisterInFactory(const ClassIDKey &id)
{
Factory::instance().RegCreateFn(id, CreateInstance);
}
};
#endif