OpenMD 3.2
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 following paper when you publish your work:
33 *
34 * [1] Drisko et al., J. Open Source Softw. 9, 7004 (2024).
35 *
36 * Good starting points for code and simulation methodology are:
37 *
38 * [2] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
39 * [3] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
40 * [4] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
41 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
42 * [6] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
43 * [7] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
44 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
45 * [9] Drisko & Gezelter, J. Chem. Theory Comput. 20, 4986-4997 (2024).
46 */
47
48/**
49 * @file GenericFactory.hpp
50 * @author Teng Lin
51 * @date 10/24/2004
52 * @version 1.0
53 */
54
55#ifndef UTIL_GENERICFACTORY_HPP
56#define UTIL_GENERICFACTORY_HPP
57
58#include <cassert>
59#include <map>
60#include <string>
61#include <vector>
62
63namespace OpenMD {
64
65 /**
66 * @class GenericFactory GenericFactory.hpp "utils/GenericFactory.hpp"
67 * @brief GenericFactory is a template based Object Factory
68 * Factory pattern is used to define an interface for creating an object.
69 *
70 * @param Object the base class of the hierarchy for which you provide the
71 object factory.
72 * @param IdentType the object that identifies the type of the concrete
73 object. Default type is std::string * @param Creator the callable entity
74 that creates objects. This type must support operator(),
75 * taking no parameters and returning a pointer to Object. Default type is
76 function pointer.
77 *
78 * Usage:
79 * @code
80 * //Shape class
81 * class Shape {
82 * ...
83 * };
84 *
85 * //instantiating a new object factory
86 * using ShapeFactory = GenericFactory<Shape>;
87 *
88 * //Line class
89 * class Line : public Shape{
90 * ...
91 * };
92 *
93 * //declare function to create Line
94 * Shape* createLine() {
95 * return new Line;
96 * }
97 *
98 * //register createLine
99 * //note: must put ShapeFactory::getInstance()->registerCreator("Line",
100 createLine) on the right
101 * //hand side, otherwise the compiler will consider it as a function
102 declaration
103 * const bool registeredLine =
104 ShapeFactory::getInstance()->registerCreator("Line", createLine);
105 *
106 * //Circle class
107 * class Circle : public Shape{
108 * ...
109 * };
110 *
111 * //declare function to create Circle
112 * Shape* createCircle() {
113 * return new Circle;
114 * }
115 *
116 * //register createCircle
117 * const bool registeredCircle =
118 ShapeFactory::getInstance()->registerCreator("Circle", createCircle);
119 *
120 * //create object by ident
121 * Line* line = ShapeFactory::getInstance()->createObject("Line");
122 * Circle* circle = ShapeFactory::getInstance()->createObject("Circle");
123 * @endcode
124 *
125 * Or the user can use predefined macro DECLARE_CREATOR and REGISTER_CREATOR
126 * @code
127 * //Shape class
128 * class Shape {
129 * ...
130 * };
131 *
132 * //instantiating a new object factory
133 * using ShapeFactory = GenericFactory<Shape>;
134 *
135 * //Line class
136 * class Line : public Shape{
137 * ...
138 * };
139 *
140 * //declare function using macro
141 * DECLARE_CREATOR(Shape, Line)
142 *
143 * //register using macro
144 * REGISTER_CREATOR(ShapeFactory, "Line", Line);
145
146 * //Circle class
147 * class Circle : public Shape{
148 * ...
149 * };
150 *
151 * //declare function using macro
152 * DECLARE_CREATOR(Shape, Circle)
153 *
154 * //register using macro
155 * REGISTER_CREATOR(ShapeFactory, "Circle", Circle);
156 * @endcode
157 */
158 template<class Object, typename IdentType = std::string,
159 typename Creator = Object* (*)()>
161 public:
163 using CreatorMapType = std::map<IdentType, Creator>;
164
165 /**
166 * Returns an instance of object factory
167 * @return an instance of object factory
168 */
169 static FactoryType* getInstance() {
170 if (instance_ == NULL) instance_ = new FactoryType;
171 return instance_;
172 }
173
174 /**
175 * Registers a creator with a type identifier
176 * @return true if registration is succeed, otherwise return false
177 * @param id the identification of the concrete object
178 * @param creator the object responsible to create the concrete object
179 */
180 bool registerCreator(const IdentType& id, Creator creator) {
181 return creatorMap_.insert(CreatorMapType::value_type(id, creator)).second;
182 }
183
184 /**
185 * Unregisters the creator for the given type identifier. If the type
186 * identifier was previously registered, the function returns true.
187 * @return truethe type identifier was previously registered and the creator
188 * is removed, otherwise return false
189 * @param id the identification of the concrete object
190 */
191 bool unregisterCreator(const IdentType& id) {
192 return creatorMap_.erase(id) == 1;
193 }
194
195 /**
196 * Looks up the type identifier in the internal map. If it is found, it
197 * invokes the corresponding creator for the type identifier and returns its
198 * result.
199 * @return a pointer of the concrete object, return NULL if no creator is
200 * registed for creating this concrete object
201 * @param id the identification of the concrete object
202 */
203 Object* createObject(const IdentType& id) {
204 typename CreatorMapType::iterator i = creatorMap_.find(id);
205 if (i != creatorMap_.end()) {
206 // invoke functor to create object
207 return (i->second)();
208 } else {
209 return NULL;
210 }
211 }
212
213 /**
214 * Returns all of the registed type identifiers
215 * @return all of the registed type identifiers
216 */
217 std::vector<IdentType> getIdents() {
218 std::vector<IdentType> idents;
219 typename CreatorMapType::iterator i;
220
221 for (i = creatorMap_.begin(); i != creatorMap_.end(); ++i) {
222 idents.push_back(i->first);
223 }
224
225 return idents;
226 }
227
228 public:
229 static FactoryType* instance_;
230 CreatorMapType creatorMap_;
231 };
232
233 /** write out all of the type identifiers to an output stream */
234 template<typename O, typename I, typename C>
235 std::ostream& operator<<(std::ostream& o, GenericFactory<O, I, C>& factory) {
236 std::vector<I> idents;
237 std::vector<I>::iterator i;
238
239 idents = factory.getIdents();
240
241 o << "Avaliable type identifiers in this factory: " << std::endl;
242 for (i = idents.begin(); i != idents.end(); ++i) {
243 o << *i << std::endl;
244 }
245
246 return o;
247 }
248
249 // static template class member
250 template<class Object, typename IdentType, typename Creator>
251 GenericFactory<Object, IdentType, Creator>*
252 GenericFactory<Object, IdentType, Creator>::instance_;
253
254#define DECLARE_CREATOR(abstractObject, concreteObject) \
255 inline abstractObject* create##concreteObject() { return new concreteObject; }
256
257#define REGISTER_CREATOR(factory, ident, concreteObject) \
258 const bool registered##concreteObject = \
259 factory::getInstance()->registerCreator(ident, create##concreteObject);
260} // namespace OpenMD
261
262#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.