4 * Abstract Factory Classes
6 * Portable Windows Library
8 * Copyright (C) 2004 Post Increment
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Post Increment
24 * Contributor(s): ______________________________________.
27 * Revision 1.7 2004/05/23 12:33:56 rjongbloed
28 * Made some subtle changes to the way the static variables are instantiated in
29 * the factoris to fix problems with DLL's under windows. May not be final solution.
31 * Revision 1.6 2004/05/19 06:48:39 csoutheren
32 * Added new functions to allow handling of singletons without concrete classes
34 * Revision 1.5 2004/05/18 06:01:06 csoutheren
35 * Deferred plugin loading until after main has executed by using abstract factory classes
37 * Revision 1.4 2004/05/18 02:32:08 csoutheren
38 * Fixed linking problems with PGenericFactory classes
40 * Revision 1.3 2004/05/13 15:10:51 csoutheren
41 * Removed warnings under Windows
43 * Revision 1.2 2004/05/13 14:59:00 csoutheren
44 * Removed warning under gcc
46 * Revision 1.1 2004/05/13 14:53:35 csoutheren
47 * Add "abstract factory" template classes
64 #pragma warning(disable:4786)
69 * These templates implement an Abstract Factory that allows
70 * creation of a class "factory" that can be used to create
71 * "concrete" instance that are descended from a abstract case class
73 * Given an abstract class A with a descendant concrete class B, the
74 * concrete class is registered by instantiating the PAbstractFactory
77 * PAbstractFactory<A, B> aFactory("B");
79 * To instantiate the an object of type B, use the following
81 * A * b = PGenericFactory<A>::CreateInstance("B");
83 * A vector containing the names of all of the concrete classes for an
84 * abstract type can be obtained as follows:
86 * std::vector<PString> list = PGenericFactory<A>::GetKeyList()
88 * Note that these example assumes that the "key" type for the factory
89 * registration is of the default type PString. If a different key type
90 * is needed, then it is necessary to specify the key type:
92 * PAbstractFactory<C, D, unsigned> aFactory(42);
93 * C * d = PGenericFactory<C, unsigned>::CreateInstance(42);
94 * std::vector<unsigned> list = PGenericFactory<C, unsigned>::GetKeyList()
96 * Finally, note that the factory lists are all thread safe for addition,
97 * creation, and obtaining the key lists
101 template <class AbstractType
, typename TypeKey
= PString
>
102 class PGenericFactory
105 typedef AbstractType
* (*CreatorFunctionType
)();
109 : creator(NULL
), isSingleton(FALSE
), instance(NULL
)
111 AbstractInfo(CreatorFunctionType creat
, BOOL single
)
112 : creator(creat
), isSingleton(single
), instance(NULL
)
114 AbstractInfo(AbstractType
* inst
, BOOL single
)
115 : creator(NULL
), isSingleton(single
), instance(inst
)
117 CreatorFunctionType creator
;
119 AbstractType
* instance
;
122 typedef std::map
<TypeKey
, AbstractInfo
> KeyMap
;
123 typedef std::vector
<TypeKey
> KeyList
;
125 static AbstractType
* CreateInstance(const TypeKey
& key
)
127 PWaitAndSignal
m(GetMutex());
128 KeyMap
& keyMap
= GetKeyMap();
129 AbstractType
* instance
= NULL
;
130 typename
KeyMap::const_iterator entry
= keyMap
.find(key
);
131 if (entry
!= keyMap
.end()) {
132 if (entry
->second
.isSingleton
&& entry
->second
.instance
!= NULL
)
133 instance
= entry
->second
.instance
;
134 else if (entry
->second
.creator
!= NULL
)
135 instance
= (*(entry
->second
.creator
))();
140 static void Register(const TypeKey
& key
, CreatorFunctionType func
, BOOL isSingleton
)
142 Register(key
, AbstractInfo(func
, isSingleton
));
145 static void Register(const TypeKey
& key
, AbstractType
* instance
, BOOL isSingleton
)
147 Register(key
, AbstractInfo(instance
, isSingleton
));
150 static void Register(const TypeKey
& key
, const AbstractInfo
& info
)
152 PWaitAndSignal
m(GetMutex());
153 KeyMap
& keyMap
= GetKeyMap();
154 if (keyMap
.find(key
) == keyMap
.end())
158 static BOOL
IsSingleton(const TypeKey
& key
)
160 PWaitAndSignal
m(GetMutex());
161 KeyMap
& keyMap
= GetKeyMap();
162 if (keyMap
.find(key
) == keyMap
.end())
164 return keyMap
[key
].isSingleton
;
167 static KeyList
GetKeyList()
169 PWaitAndSignal
m(GetMutex());
170 KeyMap
& keyMap
= GetKeyMap();
172 typename
KeyMap::const_iterator entry
;
173 for (entry
= keyMap
.begin(); entry
!= keyMap
.end(); ++entry
)
174 list
.push_back(entry
->first
);
178 static PMutex
& GetMutex()
180 return GetFactory().mutex
;
183 static KeyMap
& GetKeyMap()
185 return GetFactory().keyMap
;
193 static PGenericFactory
& GetFactory()
195 static PGenericFactory factory
;
203 PGenericFactory(const PGenericFactory
&) {}
204 void operator=(const PGenericFactory
&) {}
208 template <class AbstractType
, class ConcreteType
, typename TypeKey
= PString
>
209 class PAbstractFactory
212 PAbstractFactory(const TypeKey
& key
)
214 PGenericFactory
<AbstractType
>::Register(key
, &CreateInstance
, FALSE
);
217 static AbstractType
* CreateInstance()
219 return new ConcreteType
;
223 PAbstractFactory(const PAbstractFactory
&) {}
224 void operator=(const PAbstractFactory
&) {}
228 template <class AbstractType
, class ConcreteType
, typename TypeKey
= PString
>
229 class PAbstractSingletonFactory
232 PAbstractSingletonFactory(const TypeKey
& key
)
234 PGenericFactory
<AbstractType
>::Register(key
, &GetInstance(), TRUE
);
237 static ConcreteType
& GetInstance()
239 static ConcreteType instance
;
244 PAbstractSingletonFactory(const PAbstractSingletonFactory
&) {}
245 void operator=(const PAbstractSingletonFactory
&) {}
249 #endif // _PFACTORY_H