ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/branches/new_design/OOPSE-2.0/src/utils/GenericFactory.hpp
Revision: 1829
Committed: Thu Dec 2 05:14:58 2004 UTC (19 years, 8 months ago) by tim
File size: 7601 byte(s)
Log Message:
minor fix

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 tim 1829 * @param IdentType the object that identifies the type of the concrete object. Default type is std::string * @param Creator the callable entity that creates objects. This type must support operator(),
48 tim 1641 * taking no parameters and returning a pointer to Object. Default type is function pointer.
49     *
50 tim 1643 * Usage:
51 tim 1641 * @code
52     * //Shape class
53     * class Shape {
54     * ...
55     * };
56     *
57     * //instantiating a new object factory
58     * typedef GenericFactory<Shape> ShapeFactory;
59     *
60     * //Line class
61     * class Line : public Shape{
62     * ...
63     * };
64     *
65     * //declare function to create Line
66     * Shape* createLine() {
67     * return new Line;
68     * }
69     *
70     * //register createLine
71 tim 1643 * //note: must put ShapeFactory::getInstance()->registerCreator("Line", createLine) on the right
72     * //hand side, otherwise the compiler will consider it as a function declaration
73     * const bool registeredLine = ShapeFactory::getInstance()->registerCreator("Line", createLine);
74 tim 1641 *
75     * //Circle class
76     * class Circle : public Shape{
77     * ...
78     * };
79     *
80     * //declare function to create Circle
81     * Shape* createCircle() {
82     * return new Circle;
83     * }
84     *
85     * //register createCircle
86 tim 1643 * const bool registeredCircle = ShapeFactory::getInstance()->registerCreator("Circle", createCircle);
87 tim 1641 *
88     * //create object by ident
89     * Line* line = ShapeFactory::getInstance()->createObject("Line");
90     * Circle* circle = ShapeFactory::getInstance()->createObject("Circle");
91     * @endcode
92 tim 1643 *
93     * Or the user can use predefined macro DECLARE_CREATOR and REGISTER_CREATOR
94     * @code
95     * //Shape class
96     * class Shape {
97     * ...
98     * };
99     *
100     * //instantiating a new object factory
101     * typedef GenericFactory<Shape> ShapeFactory;
102     *
103     * //Line class
104     * class Line : public Shape{
105     * ...
106     * };
107     *
108     * //declare function using macro
109     * DECLARE_CREATOR(Shape, Line)
110     *
111     * //register using macro
112     * REGISTER_CREATOR(ShapeFactory, "Line", Line);
113    
114     * //Circle class
115     * class Circle : public Shape{
116     * ...
117     * };
118     *
119     * //declare function using macro
120     * DECLARE_CREATOR(Shape, Circle)
121     *
122     * //register using macro
123     * REGISTER_CREATOR(ShapeFactory, "Circle", Circle);
124     * @endcode
125 tim 1641 */
126     template<class Object, typename IdentType = std::string, typename Creator = Object* (*)()>
127     class GenericFactory {
128 tim 1587 public:
129 tim 1641 typedef GenericFactory<Object, IdentType, Creator> FactoryType;
130     typedef std::map<IdentType, Creator> CreatorMapType;
131 tim 1587
132 tim 1641 /**
133     * Returns an instance of object factory
134     * @return an instance of object factory
135     */
136     static FactoryType* getInstance(){
137     if (instance_ == NULL)
138     instance_ = new FactoryType;
139 tim 1592 return instance_;
140     }
141 tim 1587
142 tim 1641 /**
143     * Registers a creator with a type identifier
144     * @return true if registration is succeed, otherwise return false
145     * @id the identification of the concrete object
146     * @creator the object responsible to create the concrete object
147     */
148     bool registerCreator(const IdentType& id, Creator creator) {
149     return creatorMap_.insert(
150     CreatorMapType::value_type(id, creator)).second;
151     }
152 tim 1587
153 tim 1641 /**
154     * Unregisters the creator for the given type identifier. If the type identifier
155     * was previously registered, the function returns true.
156     * @return truethe type identifier was previously registered and the creator is removed,
157     * otherwise return false
158     * @id the identification of the concrete object
159     */
160     bool unregisterCreator(const IdentType& id) {
161     return creatorMap_.erase(id) == 1;
162 tim 1592 }
163 tim 1587
164 tim 1641 /**
165     * Looks up the type identifier in the internal map. If it is found, it invokes the
166     * corresponding creator for the type identifier and returns its result.
167     * @return a pointer of the concrete object, return NULL if no creator is registed for
168     * creating this concrete object
169 tim 1642 * @param id the identification of the concrete object
170 tim 1641 */
171     Object* createObject(const IdentType& id) {
172     typename CreatorMapType::iterator i = creatorMap_.find(id);
173 tim 1592 if (i != creatorMap_.end()) {
174 tim 1643 //invoke functor to create object
175 tim 1641 return (i->second)();
176 tim 1592 } else {
177 tim 1641 return NULL;
178 tim 1592 }
179     }
180    
181 tim 1641 /**
182     * Returns all of the registed type identifiers
183     * @return all of the registed type identifiers
184     */
185     std::vector<IdentType> getIdents() {
186     std::vector<IdentType> idents;
187     typename CreatorMapType::iterator i;
188 tim 1592
189 tim 1641 for (i = creatorMap_.begin(); i != creatorMap_.end(); ++i) {
190     idents.push_back(i->first);
191 tim 1592 }
192 tim 1641
193     return idents;
194 tim 1592 }
195 tim 1641
196     public:
197     static FactoryType* instance_;
198 tim 1592 CreatorMapType creatorMap_;
199 tim 1587 };
200    
201 tim 1681 /** write out all of the type identifiers to an output stream */
202 tim 1641 template<typename O, typename I, typename C>
203     std::ostream& operator <<(std::ostream& o, GenericFactory<O, I, C>& factory) {
204     std::vector<I> idents;
205     std::vector<I>::iterator i;
206 tim 1587
207 tim 1641 idents = factory.getIdents();
208    
209     o << "Avaliable type identifiers in this factory: " << std::endl;
210     for (i = idents.begin(); i != idents.end(); ++i) {
211     o << *i << std::endl;
212 tim 1592 }
213    
214 tim 1641 return o;
215     }
216    
217     //static template class member
218     template<class Object, typename IdentType,typename Creator>
219     GenericFactory<Object,IdentType,Creator>* GenericFactory<Object,IdentType,Creator>::instance_ ;
220    
221 tim 1643
222 tim 1641 #define DECLARE_CREATOR(abstractObject, concreteObject) \
223 tim 1643 inline abstractObject* create##concreteObject(){\
224 tim 1641 return new concreteObject;\
225     }
226    
227 tim 1643 #define REGISTER_CREATOR(factory, ident, concreteObject) \
228     const bool registered##concreteObject = factory::getInstance()->registerCreator(ident, create##concreteObject);
229    
230    
231 tim 1592 }//namespace oopse
232     #endif //UTIL_GENERICFACTORY_HPP
233