Design Pattern et C++ ?

Design Pattern et C++ ? - C++ - Programmation

Marsh Posté le 03-05-2002 à 00:01:06    

Salut!
 
Alors voilà, mon problème est le suivant,  
j'ai une classe de base IMAGE et des classes filles JPEG,TGA,TIFF,
,et tous les formats que vous voulez qui heritent d'IMAGE.
 
IMAGE possède la structure de donnee generale d'une image mode
RGBA (datas, header,tailles,....), elle permet de l'afficher, de
la possitionner dans l'espace si je puis dire,...
 
les filles effectue les taches de lecture/decompression
qui leur sont propres et renvoi la structure de donnee...
 
C'est le schema que je souhaite utilisé, seulement, dans mon main
je NE VEUX PAS DECLARER JPEG,TGA,TIFF,...
je veux faire un truc comme:
IMAGE herbe;
herbe.Load("herbe.jpg" );//jpg
herbe.Position(0,1,2);
herbe.Display();
 
aussi bien que:
IMAGE herbe;
herbe.Load("herbe.tga" );//tga
herbe.Position(0,1,2);
herbe.Display();
 
et en fonction, le systeme selectionne la classe adequate, mais  
je travail toujour avec la classe de base qui recupere le resultat..
 
enfin,c'est tout con? ou non, car ds ce sens je ne trouve pas d'infos...
on m'a parlé des design pattern...et des factory mais je ne sais  
pas comment ca marche..

Reply

Marsh Posté le 03-05-2002 à 00:01:06   

Reply

Marsh Posté le 03-05-2002 à 00:34:40    

Alors, pas 1 pro du C++ !!!

Reply

Marsh Posté le 03-05-2002 à 00:39:28    

djkurgan a écrit a écrit :

Alors, pas 1 pro du C++ !!!  



Non, moi c'est Java. Elle te vient de là l'idée de la Factory ?


---------------
Le site de ma maman
Reply

Marsh Posté le 03-05-2002 à 00:42:51    

Non, d'un gars qui fait du soft/hard a matra, tu sais
s'il ya une solution en c++ pour ce probleme...

Reply

Marsh Posté le 03-05-2002 à 08:39:09    

c'est le pattern "abstract factory" ça.


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 03-05-2002 à 09:06:48    

bah, justement, j'en sais rien....je ne sais meme pas si
c'est la solution a mon probleme et si oui, comment ca marche...

Reply

Marsh Posté le 03-05-2002 à 10:02:21    

Oui, c'est la solution, c'est à ça que sert ce pattern justement. Sauf que j'ai pas d'implémentations sous la main, et que je n'ai même pas le bouquin qui la présente ici.
 
Après quelques recherches, j'ai trouvé ça :  
http://www.dofactory.com/patterns/pattern_abstract.asp
 
Le modèle UML montre bien les classes en relations. Mais je rajouterais un patterns singleton sur la Contrete Factory, une instance suffit.


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 03-05-2002 à 10:17:22    

Plus j'y pense, plus l'abstract factory me semble être un poil gros (et pas super adapté, tu n'as pas besoin de factory abstraite en fait) pour tes besoins. Une factory classique suffira :  
 
C'est pas du vrai C++, mais les idées y sont.

Code :
  1. class imageFactory {
  2.     IMAGE *createImage (const String &fileName){
  3.          switch (fileName.getExtension ()) {
  4.          case "TGA"
  5.              return new IMAGETGA (fileName);
  6.              break;
  7.          case "JPG"
  8.              return new IMAGEJPG (fileName);
  9.              break;
  10.          }
  11.     }
  12. };


 
Utilisation :
 
imageFactory creator;
IMAGE *herbe = creator.createImage ("herbe.jpg" );
herbe->Position(0,1,2);
herbe->Display();  
 
 
imageFactory creator;
IMAGE *herbe = creator.createImage ("herbe.tga" );
herbe->Position(0,1,2);
herbe->Display();


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 03-05-2002 à 10:35:44    

ok! merci bien, une question conne, je suppose que ton  
IMAGETGA et IMAGEJPG sont les classes spécialisée (filles) et  
IMAGE la classe de base, la factory est 'à coté' sans aucune relation avec les autres...enfin merci, je commence à bien
voir l'utilite, ca va me permettre de faire un code plus propre
et modulaire (enfin, j'espere), je vais etudier le lien que  
tu m'as filé..

Reply

Marsh Posté le 03-05-2002 à 10:37:52    

quel est la difference entre l'abstract et concrete (celle que tu m'as filé) factory?

Reply

Marsh Posté le 03-05-2002 à 10:37:52   

Reply

Marsh Posté le 03-05-2002 à 10:45:17    

djkurgan a écrit a écrit :

quel est la difference entre l'abstract et concrete (celle que tu m'as filé) factory?  




 
L'abstract factory permet d'avoir des factory différentes suivant les cas. L'exemple le plus souvent présent est celui des interface graphiques.
 
On a une AbstractFactory qui contient les call de création d'objets graphiques (window, textfield), et des concretes factory capable de créer ces objets suivant le toolkit utilisé (Motif, MFC, etc...). Chaque objet créé a une classe abstraite poour le manipuler (AbstractWindow, AbstractTextField) et des classes concrete pour l'implémentation (MotifWindow, MFCWindow). Mais le codeur ne manipule que les abstraites, ne s'interressant pas au type réel des classes.
 
Donc comme tu peux le voir, c'est un peu plus complexe que ce que tu as réellement besoin.


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 03-05-2002 à 10:54:13    

C'est donc un niveau d'abstraction suplementaire...
je verrais à l'occasion si j'en ai besoin... :-), on ne  
sait jamais, enfin merci pour le deblocage, j'en avais besoin...
en effet je vais applique cette methode à d'autre module comme
le mouvement que je specialise en cinematique et dynamique...
merci et a+

Reply

Marsh Posté le 03-05-2002 à 12:09:10    

Une des Bibles indispensable en POO: "Design Patterns: Elements of Reusable Object-Oriented", Gamma et al., Addison-Wesley
Aussi très intéressant pour ceux qui n'ont pas compris à quoi sert la POO.
Y avait une version Web, mais je la trouve plus. Si qq'un l'a... Merci

Reply

Marsh Posté le 03-05-2002 à 12:15:40    

Code :
  1. class imageFactory {
  2.     IMAGE *createImage (const String &fileName){
  3.          switch (fileName.getExtension ()) {
  4.          case "TGA"
  5.              return new IMAGETGA (fileName);
  6.              break;
  7.          case "JPG"
  8.              return new IMAGEJPG (fileName);
  9.              break;
  10.          }
  11.     }
  12. };


 
Pourquoi ne pas mettre "createImage" comme membre "static" de la classe "IMAGE" ?

Reply

Marsh Posté le 03-05-2002 à 12:22:22    

kenshiro182 a demandé avec son clavier a écrit :

 
Pourquoi ne pas mettre "createImage" comme membre "static" de la classe "IMAGE" ?  




 
C'est effectivement mieux. Je bosse dans un langage ou la notion de static n'existe pas, j'y pense donc rarement.

 

[jfdsdjhfuetppo]--Message édité par kadreg le 03-05-2002 à 12:23:01--[/jfdsdjhfuetppo]


---------------
brisez les rêves des gens, il en restera toujours quelque chose...  -- laissez moi troller sur discu !
Reply

Marsh Posté le 03-05-2002 à 12:37:47    

kadreg a écrit a écrit :

c'est le pattern "abstract factory" ça.  



BTW Je crois que le "Factory Method" suffit pour ce problème... Le "Abstract Factory" est un peu trop compliqué pour ca.

Reply

Marsh Posté le 03-05-2002 à 12:47:20    

djkurgan a écrit a écrit :

:-)


:lol: Mais quel touriste ce djkurgan.

Reply

Marsh Posté le 03-05-2002 à 13:25:01    

Tjrs a glander ce cherrytree...:sleep:

Reply

Marsh Posté le 03-05-2002 à 14:21:57    

Donc, fonction membre static de la classe de base ou factory?
l'objectif etant la modularite et la reutilisabilite du code...

Reply

Marsh Posté le 03-05-2002 à 14:28:48    

djkurgan a écrit a écrit :

Tjrs a glander ce cherrytree...:sleep:  



Yaisse !


---------------
Le site de ma maman
Reply

Marsh Posté le 03-05-2002 à 15:49:27    

j'ai un doute, s'il on met createimage ds la classe de base,  
cette fct creant un objet relatif à ces propres classe filles,
la classe de base devient dependante des classes filles, a-t-on
le droit au niveau de la norme s'il on veut un code propre?

Reply

Marsh Posté le 03-05-2002 à 16:15:59    

:jap:

Reply

Marsh Posté le 03-05-2002 à 18:26:57    

pas une petite idee?

Reply

Marsh Posté le 03-05-2002 à 19:09:57    

djkurgan a écrit a écrit :

j'ai un doute, s'il on met createimage ds la classe de base,  
cette fct creant un objet relatif à ces propres classe filles,
la classe de base devient dependante des classes filles, a-t-on
le droit au niveau de la norme s'il on veut un code propre?  



J suis pas sur d'avoir bien compris la question mais... c'est le but -> le but (factory method) est de ne pas savoir avec kel type d'images tu bosses dans le code client. Si tu ne fais pas ca, c'est dans le code client qui voudrait choisir kel type d'objet devra être créé. J'éspère que ca répond à ta question.

 

[jfdsdjhfuetppo]--Message édité par MelloW le 03-05-2002 à 19:14:46--[/jfdsdjhfuetppo]

Reply

Marsh Posté le 03-05-2002 à 19:28:30    

Reply

Marsh Posté le 03-05-2002 à 19:41:42    

j'ai bien compris, c'etait en reaction au post de kenshiro182
qui proposait de mettre la fonction createimage ds la classe
de base IMAGE en membre statique à la place d'utiliser
la factory...
 
seulement, je me demandais si ca ne transgressai pas les regles
de prog objet d'instancier les classes filles ds la  
classe de base...
 
donc, au final la meilleur methode pour ce que je
veux faire est la factory? oui/non

Reply

Marsh Posté le 03-05-2002 à 19:50:50    

(perso a la base j'avais fait comme toi, puis un jour j'en ai eu marre, et devant le peu de gain apporté par les classes dérivés & cie j'ai tout envoyé promener . j'ai now une seule grosse classe qui fait jpeg / png bla &bla et ca marche impec . Bref, désolé pour le of topic)

Reply

Marsh Posté le 03-05-2002 à 20:01:13    

oui, mais question reutilisabilite et modularite, je trouve  
pas ca genial, actuellement, j'ai une classe qui fait tout
egalement, seulement les images sont un cas particulier ou  
"ca peut passer" mais j'ai d'autres modules ou la ca devient
de vrai usines si je met tout ds une classe...enfin chacun
sa methode, mais je trouve celle la assez elegante.

Reply

Marsh Posté le 03-05-2002 à 20:22:08    

djkurgan a écrit a écrit :

j'ai bien compris, c'etait en reaction au post de kenshiro182
qui proposait de mettre la fonction createimage ds la classe
de base IMAGE en membre statique à la place d'utiliser
la factory...
 
seulement, je me demandais si ca ne transgressai pas les regles
de prog objet d'instancier les classes filles ds la  
classe de base...
 
donc, au final la meilleur methode pour ce que je
veux faire est la factory? oui/non  



Si tu veux qqchose de modulaire, évolutif oui. Je ne vois vraiment pas l'intêret à le déclarer static.

Reply

Marsh Posté le 03-05-2002 à 21:42:34    

pourquoi dériver imagejpeg, imagepng de image ? c'est un peu comme si les exporteurs d'un document dérivaient de la classe document : ça n'a rien à faire là.  
 
j'aime bien la méthode kadreg, sauf que je remplace les "return new imagetga" par des appels à des classes de sérialisation. tu as une classe imageFactory (var globale, singleton) qui s'occupe de trouver le bon loader et de renvoyer l'image chargée. comment réalise-t-elle ça ? elle a une collection de classes 'sérialisatrices' qui s'occupent de sauver / charger un fichier.
 
class serializer
{
  virtual char* getExtension(); // renvoie un pointeur vers une chaîne statique identifiant l'extension du fichier que la classe traite
 
  virtual object* load(char* str);
  virtual bool save(object* o);
};
 
ta classe imageFactory recense des serializers :
 
class imageFactory
{
  bool registerSerializer(serializer* sz);
  image* loadImage(char* path);
  bool saveImage(image* image, char* extension);
 
// variables :
  serializer* serializers; // je schématise ... registerSerializer stocke les serializer là-dedans.
};
 
le but est ici de dériver de serializer dès que tu veux implémenter un nouveau format d'objet :
 
class pgnSerializer : public serializer
{
  virtual char* getExtension() { return "PNG"; }
 
  virtual object* load(char* str); // le code pour charger un png ...
  virtual bool save(object* o);   // le code pour sauver un png ...
};
 
au début de ton programme, tu instancies une variable imageFactory :
 
imageFactory* imf = new imageFactory;
 
tu registers tes serializers :
 
img->registerSerializer(new pngSerializer);
img->registerSerializer(new jpgSerializer);
 
etc.
 
pour charger une image, tu n'as plus qu'à appeler loadImage de imageFactory :
 
image* img = imf->loadImage("monimage.jpeg" );
 
loadImage va chopper l'extension de l'image, la comparer avec sa collection de serializer (en appelant serializer->getExtension()), appeler load() dès que la comparaison est bonne. et *pouf*, tu as ton image.
 
tu veux sauver, tu appelles :
 
imf->saveImage(img, "PNG" );
 
saveImage suit le même chemin que loadImage.  
 
maintenant, ton document (ton image) est séparée de la façon dont tu l'importes / exportes, ce qui est une "Good Thing". dans ta version précédente, il t'était impossible de :
 
* sauver en png une image importée en jpeg sans faire des contorsions invraisemblables (au chargement du jpeg, la factory renvoie une imagejpeg, qui doit contenir les méthodes save / load, maintenant, comment sauver ça en png, vu que la procédure save est dans la classe imagepng ? urrrgh).
 
* étendre la classe image. tu veux définir proceduralImage : public image, qui rajoute (par exemple) une méthode perlinNoise() qui se charge de faire des jolis nuages. tu redérives tout pour la sauver ?  
 
//
 
y'a de quoi grandement améliorer tout ça (classe de base, isKindOf(), etc.), mais tu dois voir l'idée : séparer les choses qui n'ont rien à faire ensemble.

Reply

Marsh Posté le 04-05-2002 à 01:21:39    

Merci, c'est tres interessant et je vais essayer de mettre en  
oeuvre cette methode, en fait le but c'est la lecture ou
creation, le parametrage, et l'affichage de texture à partir
donc d'images de formats differents,de fcts maths(procedurals),...
je vais essayer de faire qq dejà de clair sur ce
principe en utilisant une architecture adaptée, je
pense qu'avec methode serializer+factory, le code sera propre,
modulaire et reutilisable....
 
j'espere que c'est en definitive la bonne demarche....
merci pour tout

Reply

Marsh Posté le 04-05-2002 à 11:24:38    

djkurgan a écrit a écrit :

j'ai un doute, s'il on met createimage ds la classe de base,  
cette fct creant un objet relatif à ces propres classe filles,
la classe de base devient dependante des classes filles, a-t-on
le droit au niveau de la norme s'il on veut un code propre?  




 
J'ai propose de mettre la methode "factory" en membre "static" de la classe fille car:
- la classe fille ne presenterais qu'une interface (methodes virtuelles pures, a la java), bref surement quasiment pas de code
- la methode "factory" n'est pas dependante d'une instance d'un objet
 
De toutes facons, la methode "factory" aura a connaitre les differents types d'images (JpegImage, PngImage...) qu'elle peut creer...

Reply

Marsh Posté le 04-05-2002 à 11:40:26    

youdontcare...
 
Bons arguments, j'avais pas pense a separer le chargement des images...
 
Reste un probleme: tu n'as pas forcement envie de charger une image entierement (et la voir stockee entierement en memoire). Il se peut que tu veuilles par exemple decompresser par blocs de 50 pixels.
Pour un convertisseur, ca peut etre tres pratique. J'ai voulu faire des modifs d'une image jpeg dont la taille etait un truc comme 128*80000. ImageMagic (un programme en ligne de commande sous linux) chargeais tout en memoire pour une bete convertion.
 
Bref, il se peut que tes importer/exporter ne puissent pas creer un objet "image" complet.

Reply

Marsh Posté le 04-05-2002 à 12:06:59    

voui, ca fait bcp de choses, mais faudrai vous mettre d'accord...
enfin merci a+

Reply

Marsh Posté le 04-05-2002 à 12:37:41    

djkurgan a écrit a écrit :

voui, ca fait bcp de choses, mais faudrai vous mettre d'accord...
enfin merci a+  




 
hé dis, c a toi qu'appartient la décision finale, non ? :D
 
 
C a voir en fonction de tes besoins, si jamais tu ne pense pas avoir besoin de charger des 1500x8000 alors a priori tu n'auras pas a te soucier de ce que dis fabsk ;)

Reply

Marsh Posté le 04-05-2002 à 12:44:12    

chrisbk a écrit a écrit :

 
C a voir en fonction de tes besoins, si jamais tu ne pense pas avoir besoin de charger des 1500x8000 alors a priori tu n'auras pas a te soucier de ce que dis fabsk ;)  




 
Quel manipulateur ! J'ai pas dit 1500x8000 mais 128*80000 :-)
C'etait pour stocker une petite video dans un programme (hack rapide)

Reply

Marsh Posté le 04-05-2002 à 12:54:12    

fabsk a écrit a écrit :

Reste un probleme: tu n'as pas forcement envie de charger une image entierement (et la voir stockee entierement en memoire). Il se peut que tu veuilles par exemple decompresser par blocs de 50 pixels.


et ?  
 
class imageSerializer : public serializer
{
  bool canLoadSubset();
  image* loadImageSubset(char* path, RECT* load);  
};
 
je répète : séparer ce qui n'a rien à faire ensemble. si tu veux rajouter des fonctionnalités de chargement / sauvegarde, tu le fais dans une classe de base de serialisation. où est le problème ?
 

djkurgan a écrit a écrit :

voui, ca fait bcp de choses, mais faudrai vous mettre d'accord...


et toi si tu cherches LA façon de faire qui marche partout, tu vas chercher longtemps ! :)

Reply

Marsh Posté le 04-05-2002 à 12:57:59    

En fait c'est pour un moteur 3D ss Linux, je veux une architecture
modulaire, reutilisable pr faire un code evolutif aussi
bien pr moi que pour d'autre, donc je cherche la meilleur solution,
les texture, applique sur les faces 256x256 suffisant, en incrustation,
plus mais j'ai une limite par rapport aux perf, donc....
 
en opengl, j'ai des routines de recuperations de donnee ds  
la memoire tampon (selection d'une partie de l'image residente),
le resultat etant copie ds la mem texture, un truc comme
glCopyTexSubImage2D(...)
donc l'histoire ds gdes images, je me debrouille...merci, la methode
youdontcare me plait assez...
 
voilà j'ai pris la decision finale :D
 
je vais egalement acheter un bon bouquin sur design pattern,...
me formé à un code + moderne, bye et merci

Reply

Marsh Posté le 04-05-2002 à 13:13:43    

youdontcare a écrit a écrit :

pourquoi dériver imagejpeg, imagepng de image ? c'est un peu comme si les exporteurs d'un document dérivaient de la classe document : ça n'a rien à faire là.  
 
j'aime bien la méthode kadreg, sauf que je remplace les "return new imagetga" par des appels à des classes de sérialisation. tu as une classe imageFactory (var globale, singleton) qui s'occupe de trouver le bon loader et de renvoyer l'image chargée. comment réalise-t-elle ça ? elle a une collection de classes 'sérialisatrices' qui s'occupent de sauver / charger un fichier.
 
class serializer
{
  virtual char* getExtension(); // renvoie un pointeur vers une chaîne statique identifiant l'extension du fichier que la classe traite
 
  virtual object* load(char* str);
  virtual bool save(object* o);
};
 
ta classe imageFactory recense des serializers :
 
class imageFactory
{
  bool registerSerializer(serializer* sz);
  image* loadImage(char* path);
  bool saveImage(image* image, char* extension);
 
// variables :
  serializer* serializers; // je schématise ... registerSerializer stocke les serializer là-dedans.
};
 
le but est ici de dériver de serializer dès que tu veux implémenter un nouveau format d'objet :
 
class pgnSerializer : public serializer
{
  virtual char* getExtension() { return "PNG"; }
 
  virtual object* load(char* str); // le code pour charger un png ...
  virtual bool save(object* o);   // le code pour sauver un png ...
};
 
au début de ton programme, tu instancies une variable imageFactory :
 
imageFactory* imf = new imageFactory;
 
tu registers tes serializers :
 
img->registerSerializer(new pngSerializer);
img->registerSerializer(new jpgSerializer);
 
etc.
 
pour charger une image, tu n'as plus qu'à appeler loadImage de imageFactory :
 
image* img = imf->loadImage("monimage.jpeg" );
 
loadImage va chopper l'extension de l'image, la comparer avec sa collection de serializer (en appelant serializer->getExtension()), appeler load() dès que la comparaison est bonne. et *pouf*, tu as ton image.
 
tu veux sauver, tu appelles :
 
imf->saveImage(img, "PNG" );
 
saveImage suit le même chemin que loadImage.  
 
maintenant, ton document (ton image) est séparée de la façon dont tu l'importes / exportes, ce qui est une "Good Thing". dans ta version précédente, il t'était impossible de :
 
* sauver en png une image importée en jpeg sans faire des contorsions invraisemblables (au chargement du jpeg, la factory renvoie une imagejpeg, qui doit contenir les méthodes save / load, maintenant, comment sauver ça en png, vu que la procédure save est dans la classe imagepng ? urrrgh).
 
* étendre la classe image. tu veux définir proceduralImage : public image, qui rajoute (par exemple) une méthode perlinNoise() qui se charge de faire des jolis nuages. tu redérives tout pour la sauver ?  
 
//
 
y'a de quoi grandement améliorer tout ça (classe de base, isKindOf(), etc.), mais tu dois voir l'idée : séparer les choses qui n'ont rien à faire ensemble.  



Intéressant en effet (separation of concerns, le tout étant de bien définir ce que tu veux faire). Le pauvre il va se retrouver avec une tonne de ligne  :pt1cable:  :D (pt-être faire du refactoring par après serait plus judicieux). Puis j'ajouterai la chose suivante:

Code :
  1. img->registerSerializer(new pngSerializer);
  2. img->registerSerializer(new jpgSerializer);


Il faudrait mettre cela dans le constructeur du factory par exemple, pcq au sinon ton code client est dépendant de tout changement (support de nouveau formats,...).

Reply

Marsh Posté le 04-05-2002 à 13:32:38    

MelloW a écrit a écrit :

Il faudrait mettre cela dans le constructeur du factory par exemple, pcq au sinon ton code client est dépendant de tout changement (support de nouveau formats,...).


ce qui implique que la factory ait connaissance dès la compilation de tous les formats, d'où impossibilité de charger une dll en runtime avec de nouveaux formats. :non:
 
pour vraiment rajouter du code, on dérive toutes ces classes d'une classe de base, qui donne des services comme nom de la classe, nom du parent, isKindOf(), etc ... toutes ces classes sont enregistrées au chargement d'une dll dans une 'grosse' classe. l'imageFactory n'a plus qu'à demander à la 'grosse' classe qq chose comme 'instancie-moi toutes les classes dérivées de imageSerializer'. et hop, là c'est bien clean (pas de dépendance code client, possibilité de rajout de nouveaux objets via les dlls ... )
 
enfin là c'est vraiment s'il veut rajouter beaucoup de code :D

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed