OVH Cloud OVH Cloud

factory et constructeur

4 réponses
Avatar
David Bellot
Salut,

je voudrais utiliser le design pattern Factory Method pour instancier
des objets heritants d'une seule classe mere.

J'ai donc un Object et un ObjectFactory qui sont des classes abstraites
et je derive autant de ConcreteObject_x et ConcreteObjectFactory_x que
necessaire.

Pourquoi devrais-je avoir des Factory alors qu'un constructeur pourrait
aussi bien faire l'affaire ? Quel est le reel avantage (car j'ai
l'impression que ca complique un peu mon API) ?

merci

David

4 réponses

Avatar
thierry nivon
Voici un exemple concret que j'ai pu implémenté

Je crée dynamiquement des fenetres qui s'enchainent, mais en fontion
d'un paramètre la décoration des fenetres est différentes (mais pas de
changement par session)
pour eviter que chaque fenetre ait un code du type
switch (param)
case 1
a=new a1
case 2
a=new a2
...

je fait un design pattern factory
et dans la fenetre
je fais simplement
a=F.getInstance

J'espere avoir été clair

Thierry Nivon

David Bellot wrote:
Salut,

je voudrais utiliser le design pattern Factory Method pour instancier
des objets heritants d'une seule classe mere.

J'ai donc un Object et un ObjectFactory qui sont des classes abstraites
et je derive autant de ConcreteObject_x et ConcreteObjectFactory_x que
necessaire.

Pourquoi devrais-je avoir des Factory alors qu'un constructeur pourrait
aussi bien faire l'affaire ? Quel est le reel avantage (car j'ai
l'impression que ca complique un peu mon API) ?

merci

David


Avatar
thierry nivon
Desole mais mon message precedent à été coupé

Le design pattern Factory permet de faire créer des instances de types
différents, mais issus d'un ancetre commun sans que les "instanciateurs"
aient à connaitre tous les descendants :
Soit A l'ancetre commun
A1, A2, A3 des héritiers

je cree un Factory F avec un static Type qui contient le type d'instance
à creer
ainsi qu'un fonction A *F::getInstance() du genre
switch(Type)
case 1:
return new A1 ;
case 2:
return new A2 ;
....

Les "instanciateurs" savet qu'ils doivent créer un objet du type A, mais
exactement lequel, et il n'on pas besoin de connaitre tous les heritages.
Un nouvel heritage et seul le Factory change

Voici un exemple concret que j'ai pu implémenté

Je crée dynamiquement des fenetres qui s'enchainent, mais en fontion
d'un paramètre la décoration des fenetres est différentes (mais pas de
changement par session)
pour eviter que chaque fenetre ait un code du type
switch (param)
case 1
a=new a1
case 2
a=new a2
...

je fait un design pattern factory
et dans la fenetre
je fais simplement
a=F.getInstance

J'espere avoir été clair

Thierry Nivon

David Bellot wrote:
Salut,

je voudrais utiliser le design pattern Factory Method pour instancier
des objets heritants d'une seule classe mere.

J'ai donc un Object et un ObjectFactory qui sont des classes abstraites
et je derive autant de ConcreteObject_x et ConcreteObjectFactory_x que
necessaire.

Pourquoi devrais-je avoir des Factory alors qu'un constructeur pourrait
aussi bien faire l'affaire ? Quel est le reel avantage (car j'ai
l'impression que ca complique un peu mon API) ?

merci

David


Avatar
Sylvain
David Bellot wrote on 07/07/2006 19:26:

je voudrais utiliser le design pattern Factory Method pour instancier
des objets heritants d'une seule classe mere.

J'ai donc un Object et un ObjectFactory qui sont des classes abstraites
et je derive autant de ConcreteObject_x et ConcreteObjectFactory_x que
necessaire.


une factory est requise quand la définition publique du 'service'
n'inclut que des interfaces (des classes abstraites, voire abstraites
pures).

elle contribue alors à masquer tous les détails d'implémentation des
classes concrêtes - mais il y a alors généralement une seule factory
pour un "service de classe" (une arborescense de classe implémentant la
définition initiale, la "classe mère").

un exemple simple (que j'ai en tête) est une factory de clé crypto:

class Key {
public:
virtual bool isInitialized() = null;
virtual long bitSize() const = null;
virtual long process(byte* ioBuff, long& length) = null;
};

class KeyFactory {
private ou public:
KeyFactory();
public:
[static ou pas] Key getInstance(identifiant, algo, ...);
};

la factory créerait alors tous les types de clés qu'elle connait (via
des définitions non publiées).

(Rq ça marche aussi avec une factory "boite" qui créé des boites de
sardines en alu comme des boites à bonbons en papier crépon).

Sylvain.

Avatar
kanze
David Bellot wrote:

je voudrais utiliser le design pattern Factory Method pour
instancier des objets heritants d'une seule classe mere.

J'ai donc un Object et un ObjectFactory qui sont des classes
abstraites et je derive autant de ConcreteObject_x et
ConcreteObjectFactory_x que necessaire.

Pourquoi devrais-je avoir des Factory alors qu'un constructeur
pourrait aussi bien faire l'affaire ?


Si tu ne sais pas pourquoi tu veux utiliser la modèle usine, ce
n'est pas nous qui pouvons te le dire. Les modèles de conception
servent à résoudre des problèmes bien réels ; si tu n'as pas le
problème qu'ils résoudent, c'est une erreur de s'en servir.

Quel est le reel avantage (car j'ai l'impression que ca
complique un peu mon API) ?


La motivation derrière le modèle usine, c'est prèsque toujours
de simplifier la API. L'utilisateur ne voit plus les types
dérivés, que l'interface. Il déplace la logique derrière le
choix du type dérivé de chez le client à l'implémentation de la
hiérarchie. Si c'est le client qui doit choisir la classe
concrète à utiliser directement, autant le laisser appeler le
constructeur lui-même (dans le plupart des cas, au moins --
dans certains cas, comme celui des objets chargés dynamiquement,
il y a d'autres motivations pour utiliser une usine). Si le fait
qu'il y a plusieurs implémentations différentes, et leur choix,
est plutôt une question de l'implémentation, et que le client ne
le voit pas, le modèle usine permet bien de le lui cacher.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34