00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef VCSN_DESIGN_PATTERN_FACTORY_HH
00018 # define VCSN_DESIGN_PATTERN_FACTORY_HH
00019
00020 # include <exception>
00021 # include <map>
00022
00037 namespace vcsn
00038 {
00039
00040
00041
00042
00043
00044 template <class IdentifierType, class ProductType>
00045 class DefaultFactoryError
00046 {
00047 public:
00048 class Exception : public std::exception
00049 {
00050 public:
00051 Exception(const IdentifierType& unknown_id) : unknown_id_(unknown_id) {}
00052 ~Exception() throw() {};
00053 virtual const char* what()
00054 {
00055 return "Unknown object type passed to Factory.";
00056 }
00057
00058 const IdentifierType GetId()
00059 {
00060 return unknown_id_;
00061 }
00062 private:
00063 IdentifierType unknown_id_;
00064 };
00065
00066 protected:
00067 ProductType* OnUnknownType(const IdentifierType& id)
00068 {
00069 throw Exception(id);
00070 }
00071 };
00072
00073
00074
00075
00076
00077
00078 template <
00079 class AbstractProduct,
00080 class IdentifierType,
00081 class ProductCreator = AbstractProduct* (*)(),
00082 template <typename, class> class FactoryErrorPolicy = DefaultFactoryError
00083 >
00084 class Factory : public FactoryErrorPolicy<IdentifierType, AbstractProduct>
00085 {
00086 public:
00087 bool reg(const IdentifierType& id,
00088 ProductCreator creator)
00089 {
00090 typedef typename assoc_map_t::value_type value_type;
00091
00092 return associations_.insert(value_type(id, creator)).second;
00093 }
00094
00095
00096 bool unreg(const IdentifierType& id)
00097 {
00098 return associations_.erase(id) == 1;
00099 }
00100
00101
00102 AbstractProduct* create_object(const IdentifierType& id)
00103 {
00104 typename assoc_map_t::const_iterator i = associations_.find(id);
00105
00106 if (i != associations_.end())
00107 return (i->second)();
00108 return OnUnknownType(id);
00109 }
00110
00111 private:
00112 typedef std::map<IdentifierType, ProductCreator> assoc_map_t;
00113 assoc_map_t associations_;
00114 };
00115
00116 }
00117
00118
00119 #define factory_reg(factory, typeId, creationFunction) \
00120 factory.reg(typeId, creationFunction)
00121
00122 #define factory_create(factory, typeId) \
00123 factory.create_object(typeId)
00124
00125
00126 #endif // ! VCSN_DESIGN_PATTERN_FACTORY_HH