1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
/*
Implementation d'une fabrique generique basee sur des classes de politiques,
par Côme David.
*/
/*
NOTE: Dans le passage de key, on pourrait utiliser la choix automatique de type
presente dans l'article d'Alp Mestan sur les traits et classes politiques
*/
#include <iostream>
#include <map>
//La structure d'heritage, triviale a souhait
struct Shape{virtual void draw()=0;virtual Shape* Clone()=0;};
struct Square: Shape
{
void draw(){std::cout<<"Square"<<std::endl;}
Square* Clone(){return new Square(*this);}
};
struct Circle: Shape {
void draw(){std::cout<<"Circle"<<std::endl;}
Circle* Clone(){return new Circle(*this);}
};
struct Triangle : Shape{
void draw(){std::cout<<"Triangle"<<std::endl;}
Triangle* Clone(){return new Triangle(*this);}
};
//========================================================
/* Une premiere classe de politique de creation. Elle se base
sur le clonage des objets contenus dans la map.
l'utilisation des concepts de C++0x permettra de verifier s'il possede
bien une fonction membre Clone.
*/
template <typename Key,typename Object> struct CloneCreator
{
//on ajoute une cle avec un objet si la cle n'est déjÃ* pas présente
void Register(Key key,Object* obj)
{
if(m_map.find(key)==m_map.end()) { m_map[key]=obj;}
}
//Un creer un nouvel Objet via l'appel Ã* la fonction polymorphique Clone
//qui utilise aussi des retours covariants
Object* Create (const Key& key) const
{
Object* tmp=0;
typename std::map<Key,Object*>::const_iterator it=m_map.find(key);
if(it!=m_map.end()) { tmp=((*it).second)->Clone();}
/*else {throw } //On pourrai lancer une exception si on le souhaite*/
return tmp;
}
~CloneCreator()
{
typename std::map<Key,Object*>::iterator ite=m_map.end();
typename std::map<Key,Object*>::iterator it=m_map.begin();
for(;it!=ite;it++)
{
delete (*it).second;
}
}
private:
std::map<Key,Object*> m_map;
};
//========================================================
/* Une 2eme politique qui se base sur l'appel de fonction
pour generer de nouveau objets. La seule contrainte de la fonction
est sa signature. Doit renvoyer un pointeur sur Objet* et ne prendre
aucun paramètre. On pourrai aussi utiliser des boost::function si on souhaite
ameliorer le tout
*/
template <typename Key,typename Object> struct FonctionCreator
{
void Register(Key key,Object* (*obj)())
{
if(m_map.find(key)==m_map.end()) { m_map[key]=obj;}
}
Object* Create (const Key& key) const
{
Object* tmp=0;
typename std::map<Key,Object* (*)()>::const_iterator it=m_map.find(key);
if(it!=m_map.end()) { tmp=((*it).second)();}
return tmp;
}
private:
std::map<Key,Object* (*)()> m_map;
};
//========================================================
//la fabrique a proprement parle. Ne fait que des apples a la classe de poltique.
template
<
typename Key,typename Object,
template <class U,class V> class PolicieCreation = FonctionCreator
>
struct Fabrique
{
/*
C'est ici que reside toute la puissance de la fabrique: grace a cette
fonction template, on peut utiliser Register sur n'importe quoi, tant que
c'est homogene ala partie "non-cle" dans la map de la classe politique
*/
template <class Way> void Register(Key key,Way obj){creator.Register(key,obj);}
Object* Create(Key key){creator.Create(key);}
private:
PolicieCreation<Key,Object> creator;
};
/*Des fonctions de creation pour FonctionCreator
A noter: elle font appel au constructeur par defaut, mais on pourrait
tout aussi bien faire appel au constructeur de recopie, ce qui fait qu'au
final, l'effet ne serrai pas different de CloneCreator
*/
namespace
{
Shape* CreateCircle(){return new Circle();}
Shape* CreateSquare(){return new Square();}
Shape* CreateTriangle(){return new Triangle();}
}
#define CLONE
int main(int argc, char const *argv[])
{
#ifdef CLONE
Fabrique<std::string,Shape,CloneCreator> c;
c.Register("Square",new Square);
c.Register("Circle",new Circle);
c.Register("Triangle",new Triangle);
#else
Fabrique<std::string,Shape,FonctionCreator> c;
c.Register("Square",&CreateSquare);
c.Register("Circle",&CreateCircle);
c.Register("Triangle",&CreateTriangle);
#endif
Shape *p= c.Create("Circle");
p->draw();
delete p;
return 0;
} |
Partager