41 votes

Questions sur le modèle de prototype

Je suis en train de me familiariser avec les différents modèles de conception et j'ai la nette impression qu'il me manque une ou plusieurs pièces essentielles pour comprendre ce modèle particulier.

Dans tous les sites web que j'ai consultés et dans le livre GoF, je vois la méthode du clone. D'après ce que je comprends, nous avons un certain type d'objet que nous pouvons cloner lorsque nous avons besoin de différentes versions de cet objet, mais nous ne voulons pas avoir à créer manuellement chacune d'entre elles à l'aide de la commande "new" (comme en Java). Cela peut cacher son implémentation concrète. Ainsi, lorsque nous clonons, nous pouvons modifier un peu le clone et en faire ce dont nous avons besoin sans avoir à savoir comment créer cet objet à la dure. Est-ce que mon raisonnement est correct ?

On me dit également que cela peut réduire le nombre de sous-classes et donc le nombre de classes à créer. Je ne comprends pas bien cette partie. Quelqu'un pourrait-il m'aider à la comprendre ?

Ma dernière question porte sur le modèle de la fabrique abstraite (ou même de la méthode de fabrique). Ces patterns factory et le pattern prototype donnent l'impression de vouloir cacher les implémentations concrètes lors de la création de nouveaux objets. Quand est-ce une bonne idée de choisir l'un ou l'autre ?

Merci à tous !

63voto

Devendra D. Chavan Points 4707

Modèle de prototype

Le prototype donne lieu à un objet cloné qui est différent de l'objet original. L'état de l'original est le même que celui du clone, au moment du clonage. Par la suite, chaque objet peut subir un changement d'état. On peut considérer que cela revient à photocopier l'original, puis à modifier la photocopie à quelques endroits.

Exemple

  • Duplication de DVD : Duplication du dvd master pour créer plusieurs copies.
  • Objet du rapport : Considérons un objet de rapport qui contient des informations traitées à transmettre à l'interface graphique. Le rapport original contient les données dans l'ordre croissant. Maintenant, en utilisant ce modèle, on peut créer un rapport similaire mais avec des données triées par ordre décroissant.

Avantages

  • Performance : Clonage (en utilisant MemberwiseClone ) est considérablement moins coûteux que la création d'un nouvel objet à nouveau (avec la commande nouvel opérateur ). Notez qu'il est nécessaire de remplacer l'option MemberwiseClose() pour effectuer une copie profonde.
  • Les objets peuvent être clonés de manière très dynamique, sans insister sur l'instanciation préalable. Le premier objet créé peut l'être à n'importe quel moment de l'exécution de l'application, et d'autres duplications peuvent avoir lieu à tout moment ultérieur.

Quand l'utiliser

  • Lorsque les classes à instancier sont spécifiées au moment de l'exécution, par exemple, par chargement dynamique.
  • Lorsque les instances d'une classe ne peuvent avoir qu'une seule des quelques combinaisons d'état différentes. Il peut être plus pratique d'installer un nombre correspondant de prototypes et de les cloner plutôt que d'instancier la classe manuellement, à chaque fois avec l'état approprié.

Comparaison avec le modèle d'usine

Le pattern Prototype permet de créer des objets personnalisés sans connaître leur classe ni aucun détail sur la façon de les créer. C'est donc sous cet aspect qu'il ressemble beaucoup au pattern Factory Method. Dans ces deux patterns, le client peut créer n'importe quel objet de la classe dérivée sans rien savoir de sa propre structure.

Mais la différence entre les deux modèles est le fait que la Factory Method se concentre sur la création d'un objet d'un type d'objet non existant en tant qu'une fresh creation (en comprenant le sous-type exact de la classe Créateur). Le site Prototype utilise la classe elle-même, notamment la classe dérivée de self duplication action.

Modèle de méthode d'usine

Dans ce modèle, le client (ou consommateur) demande au créateur (ou usine) un type d'objet spécifique dans une hiérarchie de classes. La méthode Creator de la classe factory délègue la création de l'objet spécifique aux classes dérivées et renvoie l'objet de la classe du type demandé par le client. En substance, vous disposez d'un seul point de contact pour la création de plusieurs objets d'une hiérarchie de classes.

Vous pouvez imaginer que vous vous rendez au guichet d'une compagnie aérienne (contrôleur) et que vous demandez un billet en indiquant votre préférence quant au type de billet (première classe, exécutif ou économique). L'utilisateur ne se préoccupe pas de la manière dont le billet est généré, même si, dans une représentation objet, le billet de première classe et le billet économique sont tous deux dérivés de la classe de billet de base.

Quand utiliser

  • La flexibilité est importante (faible couplage)
  • Les objets peuvent être étendus dans des sous-classes
  • Il y a une raison spécifique pour laquelle une sous-classe serait choisie plutôt qu'une autre - cette logique fait partie de la méthode Factory.
  • Un client délègue des responsabilités à des sous-classes dans des hiérarchies parallèles.

Modèle de fabrique abstraite

La fabrique abstraite va un pas plus haut (plus abstrait) que le modèle de méthode de fabrique. Dans ce cas, on peut avoir non pas une seule, mais plusieurs fabriques avec de légères variations. Elle est chargée de créer des objets appartenant à des familles de hiérarchies de classes plutôt qu'à une seule hiérarchie de classes.

Une classe Factory spécifique existe déjà. Mais la Factory aura des méthodes légèrement différentes. Chaque méthode peut produire une instance. Le client peut choisir la méthode appropriée et obtenir l'instance.

Si vous prenez l'exemple de MVC Sur la base d'une conception architecturale parfaite, le client sera une classe de contrôleur d'entreprise tandis que les produits concrets seront tous des entités commerciales. Les usines sont des contrôleurs auxiliaires (" Helper "). Elles travaillent en association avec une demande du contrôleur d'entreprise.

Quand utiliser

  • Le système est censé être indépendant de la façon dont ses produits sont créés. Il peut même s'attendre à être indépendant de la façon dont les produits sont composés et représentés. Le terme "produit" s'applique à l'objet résultant final qu'un développeur client devra utiliser en invoquant ses méthodes.
  • Le système qui doit être configurable avec l'une des multiples familles de produits. Ainsi, la sélection effective de la famille ne se fera pas au moment du codage mais lors d'une configuration ultérieure.
  • La famille de produits est conçue pour fonctionner toujours ensemble.
  • La création est destinée à une bibliothèque de produits. Ce qui importe le plus ici, c'est l'interface concernée et non l'implémentation.

1 votes

J'apprécie le temps pris pour mener à bien cet impressionnant été. Merci !

28voto

Tom Dalling Points 10656

Vous avez le modèle du prototype, on dirait.

Comment il réduit le sous-classement

Disons que vous faites MineCraft et que vous utilisez le modèle prototype pour chaque type de bloc (par exemple, terre, pierre, etc.). Tous les objets prototypes sont en fait de la même classe Block Mais chaque objet a été doté de propriétés différentes, de sorte que son apparence et son comportement sont différents, par exemple :

prototypes.dirt = new Block;
prototypes.dirt.texture = new Image("dirt.jpg");
prototypes.dirt.hardness = 1;

prototypes.stone = new Block;
prototypes.stone.texture = new Image("stone.jpg");
prototypes.stone.hardness = 9;

Ainsi, au lieu d'une sous-classification où vous écrivez new DirtBlock o new StoneBlock vous écrirez plutôt prototypes.dirt.clone() o prototypes.stone.clone() . Aucune sous-classification n'est requise, mais vous avez toujours la possibilité de sous-classer si nécessaire.

Différences avec le modèle Factory

Quant à savoir quand choisir le modèle prototype plutôt que le modèle usine, je pense à deux situations où ils diffèrent :

  1. Vous pouvez itérer sur une liste de prototypes, mais vous ne pouvez pas itérer sur toutes les méthodes d'une fabrique abstraite^. En continuant avec le code ci-dessus, vous pourriez créer un bloc aléatoire comme ceci :

    prototypes.allValues().objectAtIndex(rand() % prototypes.size()).clone();

    Si vous utilisiez la méthode de l'usine pour fabriquer des blocs, il serait plus difficile d'obtenir un bloc aléatoire.

  2. Lorsque la création d'un objet est coûteuse, mais que la copie est bon marché, le modèle prototype sera plus efficace. Par exemple, prenez cette méthode de fabrique :

    Image loadUserImage() { 
        //loads from disk. will be slow
        return new JPEGImage("path/to/user/image.jpg"); 
    }

    Si cette méthode doit être appelée à plusieurs reprises, il serait plus efficace d'utiliser un prototype comme celui-ci :

    Image loadUserImage() {
        //copy in memory. will be fast
        return userImagePrototype.clone();
    }

^ C'est un mensonge parce que vous pouvez en fait itérer sur les méthodes selon le langage que vous utilisez, mais itérer sur un tableau est probablement une meilleure solution parce que c'est moins complexe que la réflexion/introspection.

1 votes

Une utilisation serait donc, par exemple, l'implémentation d'un constructeur de copie (profonde) avec le modèle prototype ?

16voto

rb39999 Points 101

Le gain d'efficacité de l'utilisation d'un prototype est discutable à mon avis. Il n'y aura pas de gain d'efficacité car dans la plupart des langages, la méthode clone elle-même exécute un appel à new afin de construire une nouvelle instance d'objet d'elle-même.

Le seul avantage que je vois dans l'utilisation du modèle prototype est un avantage pratique, vous savez que le clone vous donnera une copie exacte de l'objet, ce qui vous évite d'avoir à définir les attributs du nouvel objet avec les mêmes valeurs vous-même et de vous battre avec la copie profonde.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X