ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/utils/GenericFactory.hpp
Revision: 1643
Committed: Mon Oct 25 17:03:56 2004 UTC (19 years, 8 months ago) by tim
File size: 7594 byte(s)
Log Message:
adding GenericFactory Test Case. GenericFactory now can bed used to creat
ForcefieldFactory and IntegratorFactory etc.

File Contents

# User Rev Content
1 tim 1587 /*
2     * Copyright (C) 2000-2004 Object Oriented Parallel Simulation Engine (OOPSE) project
3     *
4     * Contact: oopse@oopse.org
5     *
6     * This program is free software; you can redistribute it and/or
7     * modify it under the terms of the GNU Lesser General Public License
8     * as published by the Free Software Foundation; either version 2.1
9     * of the License, or (at your option) any later version.
10     * All we ask is that proper credit is given for our work, which includes
11     * - but is not limited to - adding the above copyright notice to the beginning
12     * of your source code files, and to any copyright notice that you may distribute
13     * with programs based on this work.
14     *
15     * This program is distributed in the hope that it will be useful,
16     * but WITHOUT ANY WARRANTY; without even the implied warranty of
17     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18     * GNU Lesser General Public License for more details.
19     *
20     * You should have received a copy of the GNU Lesser General Public License
21     * along with this program; if not, write to the Free Software
22     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23     *
24     */
25    
26     /**
27 tim 1641 * @file GenericFactory.hpp
28 tim 1587 * @author Teng Lin
29 tim 1641 * @date 10/24/2004
30 tim 1587 * @version 1.0
31     */
32     #ifndef UTIL_GENERICFACTORY_HPP
33     #define UTIL_GENERICFACTORY_HPP
34 tim 1643 #include <cassert>
35 tim 1587 #include <map>
36     #include <string>
37 tim 1641 #include <vector>
38    
39 tim 1592 namespace oopse {
40 tim 1641
41     /**
42     * @class GenericFactory GenericFactory.hpp "utils/GenericFactory.hpp"
43     * @brief GenericFactory is a template based Object Factory
44     * Factory pattern is used to define an interface for creating an object.
45     *
46     * @param Object the base class of the hierarchy for which you provide the object factory.
47     * @param IdentType the object that identifies the type of the concrete object. Default type is string
48     * @param Creator the callable entity that creates objects. This type must support operator(),
49     * taking no parameters and returning a pointer to Object. Default type is function pointer.
50     *
51 tim 1643 * Usage:
52 tim 1641 * @code
53     * //Shape class
54     * class Shape {
55     * ...
56     * };
57     *
58     * //instantiating a new object factory
59     * typedef GenericFactory<Shape> ShapeFactory;
60     *
61     * //Line class
62     * class Line : public Shape{
63     * ...
64     * };
65     *
66     * //declare function to create Line
67     * Shape* createLine() {
68     * return new Line;
69     * }
70     *
71     * //register createLine
72 tim 1643 * //note: must put ShapeFactory::getInstance()->registerCreator("Line", createLine) on the right
73     * //hand side, otherwise the compiler will consider it as a function declaration
74     * const bool registeredLine = ShapeFactory::getInstance()->registerCreator("Line", createLine);
75 tim 1641 *
76     * //Circle class
77     * class Circle : public Shape{
78     * ...
79     * };
80     *
81     * //declare function to create Circle
82     * Shape* createCircle() {
83     * return new Circle;
84     * }
85     *
86     * //register createCircle
87 tim 1643 * const bool registeredCircle = ShapeFactory::getInstance()->registerCreator("Circle", createCircle);
88 tim 1641 *
89     * //create object by ident
90     * Line* line = ShapeFactory::getInstance()->createObject("Line");
91     * Circle* circle = ShapeFactory::getInstance()->createObject("Circle");
92     * @endcode
93 tim 1643 *
94     * Or the user can use predefined macro DECLARE_CREATOR and REGISTER_CREATOR
95     * @code
96     * //Shape class
97     * class Shape {
98     * ...
99     * };
100     *
101     * //instantiating a new object factory
102     * typedef GenericFactory<Shape> ShapeFactory;
103     *
104     * //Line class
105     * class Line : public Shape{
106     * ...
107     * };
108     *
109     * //declare function using macro
110     * DECLARE_CREATOR(Shape, Line)
111     *
112     * //register using macro
113     * REGISTER_CREATOR(ShapeFactory, "Line", Line);
114    
115     * //Circle class
116     * class Circle : public Shape{
117     * ...
118     * };
119     *
120     * //declare function using macro
121     * DECLARE_CREATOR(Shape, Circle)
122     *
123     * //register using macro
124     * REGISTER_CREATOR(ShapeFactory, "Circle", Circle);
125     * @endcode
126 tim 1641 */
127     template<class Object, typename IdentType = std::string, typename Creator = Object* (*)()>
128     class GenericFactory {
129 tim 1587 public:
130 tim 1641 typedef GenericFactory<Object, IdentType, Creator> FactoryType;
131     typedef std::map<IdentType, Creator> CreatorMapType;
132 tim 1587
133 tim 1641 /**
134     * Returns an instance of object factory
135     * @return an instance of object factory
136     */
137     static FactoryType* getInstance(){
138     if (instance_ == NULL)
139     instance_ = new FactoryType;
140 tim 1592 return instance_;
141     }
142 tim 1587
143 tim 1641 /**
144     * Registers a creator with a type identifier
145     * @return true if registration is succeed, otherwise return false
146     * @id the identification of the concrete object
147     * @creator the object responsible to create the concrete object
148     */
149     bool registerCreator(const IdentType& id, Creator creator) {
150     return creatorMap_.insert(
151     CreatorMapType::value_type(id, creator)).second;
152     }
153 tim 1587
154 tim 1641 /**
155     * Unregisters the creator for the given type identifier. If the type identifier
156     * was previously registered, the function returns true.
157     * @return truethe type identifier was previously registered and the creator is removed,
158     * otherwise return false
159     * @id the identification of the concrete object
160     */
161     bool unregisterCreator(const IdentType& id) {
162     return creatorMap_.erase(id) == 1;
163 tim 1592 }
164 tim 1587
165 tim 1641 /**
166     * Looks up the type identifier in the internal map. If it is found, it invokes the
167     * corresponding creator for the type identifier and returns its result.
168     * @return a pointer of the concrete object, return NULL if no creator is registed for
169     * creating this concrete object
170 tim 1642 * @param id the identification of the concrete object
171 tim 1641 */
172     Object* createObject(const IdentType& id) {
173     typename CreatorMapType::iterator i = creatorMap_.find(id);
174 tim 1592 if (i != creatorMap_.end()) {
175 tim 1643 //invoke functor to create object
176 tim 1641 return (i->second)();
177 tim 1592 } else {
178 tim 1641 return NULL;
179 tim 1592 }
180     }
181    
182 tim 1641 /**
183     * Returns all of the registed type identifiers
184     * @return all of the registed type identifiers
185     */
186     std::vector<IdentType> getIdents() {
187     std::vector<IdentType> idents;
188     typename CreatorMapType::iterator i;
189 tim 1592
190 tim 1641 for (i = creatorMap_.begin(); i != creatorMap_.end(); ++i) {
191     idents.push_back(i->first);
192 tim 1592 }
193 tim 1641
194     return idents;
195 tim 1592 }
196 tim 1641
197     public:
198     static FactoryType* instance_;
199 tim 1592 CreatorMapType creatorMap_;
200 tim 1587 };
201    
202 tim 1641 /** write out all of the type identifier to a output stream */
203     template<typename O, typename I, typename C>
204     std::ostream& operator <<(std::ostream& o, GenericFactory<O, I, C>& factory) {
205     std::vector<I> idents;
206     std::vector<I>::iterator i;
207 tim 1587
208 tim 1641 idents = factory.getIdents();
209    
210     o << "Avaliable type identifiers in this factory: " << std::endl;
211     for (i = idents.begin(); i != idents.end(); ++i) {
212     o << *i << std::endl;
213 tim 1592 }
214    
215 tim 1641 return o;
216     }
217    
218     //static template class member
219     template<class Object, typename IdentType,typename Creator>
220     GenericFactory<Object,IdentType,Creator>* GenericFactory<Object,IdentType,Creator>::instance_ ;
221    
222 tim 1643
223 tim 1641 #define DECLARE_CREATOR(abstractObject, concreteObject) \
224 tim 1643 inline abstractObject* create##concreteObject(){\
225 tim 1641 return new concreteObject;\
226     }
227    
228 tim 1643 #define REGISTER_CREATOR(factory, ident, concreteObject) \
229     const bool registered##concreteObject = factory::getInstance()->registerCreator(ident, create##concreteObject);
230    
231    
232 tim 1592 }//namespace oopse
233     #endif //UTIL_GENERICFACTORY_HPP
234