La fly-weight-factory est une usine à singletons : un objet en charge de créer d'autres objets (typiquement le TextureManager qui crée des Textures), mais qui plutôt que de recréer sans cesse les mêmes objets va les garder en mémoire pour plus tard.
Le bout de code que j'ai fourni devrait être facilement altérable si tu as un argument simple à utiliser pour requérir une texture. Tu utiliseras alors toujours cet argument pour aller piocher une texture déjà existante, ou la créer à la volée si elle n'existe pas encore.
Pour gérer les durées de vie. Ce peut être assez compexe. Une des problématiques est de savoir quand déclencher la collecte (ça revient à faire un Gabage Collector) des Textures gérées pas la FW-factory. Ce peu être retardé jusqu'aux changements de niveaux, jusqu'aux cinématiques (si tu n'utilises pas des codecs genre h264 qui mettent certains PC sur les genoux), ...
Ce que j'ai présenté est je pense altérable en :
- ne pas réalisant de delete immédiatement, mais en déplaçant le pointeur brut de la Texture vers une autre map (un weak_ptr est inexploitable car son existence est liée à celle d'un shared_ptr<>), ou en gardant un autre compteur du nombre de handles, sur une texture bien précise, qui ont été créés (le but étant de gérer le fait que l'on fasse plusieurs getTexture qui créent donc plusieurs handle vers un même pointeur)
Code:
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 class TexturesManager { .... struct HandleCounter { HandleCounter(Texture* t) : texture_(t), counter_(0) {} handle_type get(TextureManager & tm) { handle_type handle(t, Releaser(tm)); ++counter; return handle; } int count() const { return counter_;} void destroy() { assert(counter_ ==0); delete texture_; texture_=0; } private: Texture * texture_; int counter; }; handle_type operator[](Args const& args_) { std::map<...>::iterator it = textures_.find(args_); if (it == textures.end()) { Texture * t = new Texture(args); HandleCounter hc(t); it = textures_.insert(it, std::pair(args,hc)); } return it->second.get(*this); // vérifier que second ne soit pas une copie } void release(Args const& args) { 1- find hc 2- hc.release() 3- éventuels trucs intelligents si hc.count() == 0 } void releaseUnused() { erase sur les textures qui ont le count() à zéro + it->destroy } std::map<Args, HandleCounter> textures_;