OpenMD 3.0
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
GenericFactory.hpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2004-present, The University of Notre Dame. All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
32 * research, please cite the appropriate papers when you publish your
33 * work. Good starting points are:
34 *
35 * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
36 * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
37 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
38 * [4] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
39 * [5] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
40 * [6] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
41 * [7] Lamichhane, Newman & Gezelter, J. Chem. Phys. 141, 134110 (2014).
42 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
43 */
44
45/**
46 * @file GenericFactory.hpp
47 * @author Teng Lin
48 * @date 10/24/2004
49 * @version 1.0
50 */
51
52#ifndef UTIL_GENERICFACTORY_HPP
53#define UTIL_GENERICFACTORY_HPP
54
55#include <cassert>
56#include <map>
57#include <string>
58#include <vector>
59
60namespace OpenMD {
61
62 /**
63 * @class GenericFactory GenericFactory.hpp "utils/GenericFactory.hpp"
64 * @brief GenericFactory is a template based Object Factory
65 * Factory pattern is used to define an interface for creating an object.
66 *
67 * @param Object the base class of the hierarchy for which you provide the
68 object factory.
69 * @param IdentType the object that identifies the type of the concrete
70 object. Default type is std::string * @param Creator the callable entity
71 that creates objects. This type must support operator(),
72 * taking no parameters and returning a pointer to Object. Default type is
73 function pointer.
74 *
75 * Usage:
76 * @code
77 * //Shape class
78 * class Shape {
79 * ...
80 * };
81 *
82 * //instantiating a new object factory
83 * using ShapeFactory = GenericFactory<Shape>;
84 *
85 * //Line class
86 * class Line : public Shape{
87 * ...
88 * };
89 *
90 * //declare function to create Line
91 * Shape* createLine() {
92 * return new Line;
93 * }
94 *
95 * //register createLine
96 * //note: must put ShapeFactory::getInstance()->registerCreator("Line",
97 createLine) on the right
98 * //hand side, otherwise the compiler will consider it as a function
99 declaration
100 * const bool registeredLine =
101 ShapeFactory::getInstance()->registerCreator("Line", createLine);
102 *
103 * //Circle class
104 * class Circle : public Shape{
105 * ...
106 * };
107 *
108 * //declare function to create Circle
109 * Shape* createCircle() {
110 * return new Circle;
111 * }
112 *
113 * //register createCircle
114 * const bool registeredCircle =
115 ShapeFactory::getInstance()->registerCreator("Circle", createCircle);
116 *
117 * //create object by ident
118 * Line* line = ShapeFactory::getInstance()->createObject("Line");
119 * Circle* circle = ShapeFactory::getInstance()->createObject("Circle");
120 * @endcode
121 *
122 * Or the user can use predefined macro DECLARE_CREATOR and REGISTER_CREATOR
123 * @code
124 * //Shape class
125 * class Shape {
126 * ...
127 * };
128 *
129 * //instantiating a new object factory
130 * using ShapeFactory = GenericFactory<Shape>;
131 *
132 * //Line class
133 * class Line : public Shape{
134 * ...
135 * };
136 *
137 * //declare function using macro
138 * DECLARE_CREATOR(Shape, Line)
139 *
140 * //register using macro
141 * REGISTER_CREATOR(ShapeFactory, "Line", Line);
142
143 * //Circle class
144 * class Circle : public Shape{
145 * ...
146 * };
147 *
148 * //declare function using macro
149 * DECLARE_CREATOR(Shape, Circle)
150 *
151 * //register using macro
152 * REGISTER_CREATOR(ShapeFactory, "Circle", Circle);
153 * @endcode
154 */
155 template<class Object, typename IdentType = std::string,
156 typename Creator = Object* (*)()>
158 public:
160 using CreatorMapType = std::map<IdentType, Creator>;
161
162 /**
163 * Returns an instance of object factory
164 * @return an instance of object factory
165 */
167 if (instance_ == NULL) instance_ = new FactoryType;
168 return instance_;
169 }
170
171 /**
172 * Registers a creator with a type identifier
173 * @return true if registration is succeed, otherwise return false
174 * @param id the identification of the concrete object
175 * @param creator the object responsible to create the concrete object
176 */
177 bool registerCreator(const IdentType& id, Creator creator) {
178 return creatorMap_.insert(CreatorMapType::value_type(id, creator)).second;
179 }
180
181 /**
182 * Unregisters the creator for the given type identifier. If the type
183 * identifier was previously registered, the function returns true.
184 * @return truethe type identifier was previously registered and the creator
185 * is removed, otherwise return false
186 * @param id the identification of the concrete object
187 */
188 bool unregisterCreator(const IdentType& id) {
189 return creatorMap_.erase(id) == 1;
190 }
191
192 /**
193 * Looks up the type identifier in the internal map. If it is found, it
194 * invokes the corresponding creator for the type identifier and returns its
195 * result.
196 * @return a pointer of the concrete object, return NULL if no creator is
197 * registed for creating this concrete object
198 * @param id the identification of the concrete object
199 */
200 Object* createObject(const IdentType& id) {
201 typename CreatorMapType::iterator i = creatorMap_.find(id);
202 if (i != creatorMap_.end()) {
203 // invoke functor to create object
204 return (i->second)();
205 } else {
206 return NULL;
207 }
208 }
209
210 /**
211 * Returns all of the registed type identifiers
212 * @return all of the registed type identifiers
213 */
214 std::vector<IdentType> getIdents() {
215 std::vector<IdentType> idents;
216 typename CreatorMapType::iterator i;
217
218 for (i = creatorMap_.begin(); i != creatorMap_.end(); ++i) {
219 idents.push_back(i->first);
220 }
221
222 return idents;
223 }
224
225 public:
226 static FactoryType* instance_;
227 CreatorMapType creatorMap_;
228 };
229
230 /** write out all of the type identifiers to an output stream */
231 template<typename O, typename I, typename C>
232 std::ostream& operator<<(std::ostream& o, GenericFactory<O, I, C>& factory) {
233 std::vector<I> idents;
234 std::vector<I>::iterator i;
235
236 idents = factory.getIdents();
237
238 o << "Avaliable type identifiers in this factory: " << std::endl;
239 for (i = idents.begin(); i != idents.end(); ++i) {
240 o << *i << std::endl;
241 }
242
243 return o;
244 }
245
246 // static template class member
247 template<class Object, typename IdentType, typename Creator>
248 GenericFactory<Object, IdentType, Creator>*
249 GenericFactory<Object, IdentType, Creator>::instance_;
250
251#define DECLARE_CREATOR(abstractObject, concreteObject) \
252 inline abstractObject* create##concreteObject() { return new concreteObject; }
253
254#define REGISTER_CREATOR(factory, ident, concreteObject) \
255 const bool registered##concreteObject = \
256 factory::getInstance()->registerCreator(ident, create##concreteObject);
257} // namespace OpenMD
258
259#endif // UTIL_GENERICFACTORY_HPP
GenericFactory is a template based Object Factory Factory pattern is used to define an interface for ...
static FactoryType * getInstance()
Returns an instance of object factory.
bool unregisterCreator(const IdentType &id)
Unregisters the creator for the given type identifier.
Object * createObject(const IdentType &id)
Looks up the type identifier in the internal map.
bool registerCreator(const IdentType &id, Creator creator)
Registers a creator with a type identifier.
std::vector< IdentType > getIdents()
Returns all of the registed type identifiers.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.