Bonjour à tous.
J'ai réalisé une implémentation du design pattern fabrique:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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;
}
Vos avis ?
Merci.