Comprenez les différences dans les motivations :
Supposons que vous construisiez un outil dans lequel vous avez des objets et une implémentation concrète des interrelations entre les objets. Comme vous prévoyez des variations dans les objets, vous avez créé une indirection en assignant la responsabilité de créer des variantes des objets à un autre objet ( nous l'appelons l'usine abstraite ). Cette abstraction est très avantageuse car vous prévoyez que de futures extensions auront besoin de variantes de ces objets.
Une autre motivation assez intrigante dans cette ligne de pensée est le cas où tous les objets du groupe entier, ou aucun d'entre eux, auront une variante correspondante. En fonction de certaines conditions, l'une ou l'autre des variantes sera utilisée et, dans chaque cas, tous les objets doivent être de la même variante. Cela peut être un peu contre intuitif à comprendre car nous avons souvent tendance à penser que - tant que les variantes d'un objet suivent un contrat uniforme commun ( interface au sens large ), le code d'implémentation concret ne devrait jamais se casser. Ce qui intrigue ici, c'est que ce n'est pas toujours vrai, notamment lorsque le comportement attendu ne peut être modélisé par un contrat de programmation.
Un simple ( en empruntant l'idée à GoF ) est une application GUI qui émule le look-an-feel des OS MS, Mac ou Fedora. Ici, par exemple, lorsque tous les objets widgets tels que les fenêtres, les boutons, etc. ont une variante MS, à l'exception de la barre de défilement qui est dérivée de la variante MAC, l'objectif de l'outil échoue gravement.
Les cas ci-dessus constituent le besoin fondamental de Modèle de fabrique abstraite .
D'un autre côté, imaginez que vous écrivez un framework pour que de nombreuses personnes puissent construire divers outils ( comme celui des exemples ci-dessus ) en utilisant votre cadre. Par l'idée même d'un framework, vous n'avez pas besoin de le faire, bien que vous ne puissiez pas utiliser d'objets concrets dans votre logique. Vous mettez plutôt en place des contrats de haut niveau entre les différents objets et leur interaction. Pendant que vous ( en tant que développeur de cadres ) restent à un niveau très abstrait, chaque constructeur de l'outil est obligé de suivre vos structures. Cependant, ils ( les constructeurs d'outils ) ont la liberté de décider de l'objet à construire et de la manière dont tous les objets qu'ils créent vont interagir. Contrairement au cas précédent ( du modèle de fabrique abstraite ), vous ( en tant que créateur de cadre ) n'ont pas besoin de travailler avec des objets concrets dans ce cas, et peuvent plutôt rester au niveau du contrat des objets. De plus, contrairement à la deuxième partie des motivations précédentes, vous ou les constructeurs d'outils ne serez jamais confrontés à la situation de mélanger des objets provenant de variantes. Ici, alors que le code du cadre reste au niveau du contrat, chaque constructeur d'outils est limité ( par la nature même de l'affaire ) à l'utilisation de leurs propres objets. Dans ce cas, la création d'objets est déléguée à chaque implémenteur et les fournisseurs de frameworks se contentent de fournir des méthodes uniformes pour créer et renvoyer des objets. Ces méthodes sont inévitables pour les développeurs de frameworks afin de poursuivre leur code et ont un nom spécial appelé Méthode d'usine ( Modèle de méthode d'usine pour le modèle sous-jacent ).
Quelques notes :
- Si vous êtes familier avec la notion de "méthode template", vous verrez que les méthodes d'usine sont souvent invoquées à partir de méthodes template dans le cas de programmes appartenant à toute forme de framework. En revanche, les méthodes de modèle des programmes d'application sont souvent une simple mise en œuvre d'un algorithme spécifique et sont dépourvues de méthodes d'usine.
- De plus, pour l'exhaustivité de la réflexion, en utilisant le cadre ( mentionné ci-dessus ), lorsqu'un constructeur d'outils construit un outil, à l'intérieur de chaque méthode de fabrique, au lieu de créer un objet concret, il peut déléguer la responsabilité à un objet de fabrique abstrait, à condition que le constructeur d'outils prévoie des variations des objets concrets pour les extensions futures.
Code échantillon :
//Part of framework-code
BoardGame {
Board createBoard() //factory method. Default implementation can be provided as well
Piece createPiece() //factory method
startGame(){ //template method
Board borad = createBoard()
Piece piece = createPiece()
initState(board, piece)
}
}
//Part of Tool-builder code
Ludo inherits BoardGame {
Board createBoard(){ //overriding of factory method
//Option A: return new LudoBoard() //Lodu knows object creation
//Option B: return LudoFactory.createBoard() //Lodu asks AbstractFacory
}
….
}
//Part of Tool-builder code
Chess inherits BoardGame {
Board createBoard(){ //overriding of factory method
//return a Chess board
}
….
}
4 votes
Duplicata possible de Quelle est la différence fondamentale entre les patrons Factory et Abstract Factory ?
0 votes
Voir "comment l'instance a été créée" du point de vue du client, vous aiderait à comprendre le devis.
4 votes
@nawfal, les réponses dans ce fil sont affreuses.