Utilisateur:Quaivingt/Brouillon/PatronPrototype
Prototype (Patron de conception)
modifierCe patron de conception permet de définir le genre d'objet à créer en dupliquant une instance qui sert d'exemple, le prototype[1]. L'objectif de ce patron est d'économiser le temps nécessaire pour instancier des objets. Selon ce patron, une application comporte une instance d'un objet, qui sert de prototype. Cet objet comporte une méthode clone
pour créer des duplicata. Pour qu'un Objet puisse être cloné suivant le langage de programmation il peut être nécessaire de le déclarer explicitement. Par exemple en Java la classe de l'objet doit implémenter Cloneable[2].
Utilisation
modifierEn programmation informatique, le patron de conception prototype est utilisé lorsque la création d'une instance est complexe ou consommatrice en temps. Plutôt que créer plusieurs instances de la classe, on copie la première instance et on modifie la copie de façon appropriée. Laurent DEBRAUWER relève 3 cas d'usage de ce patron[3].
Exemple
modifierSupposons une classe pour interroger une base de données. À l'instanciation de cette classe on se connecte et on récupère les données de la base avant d'effectuer tous types de manipulation.
Par la suite il sera plus performant pour les futures instances de cette classe de continuer à manipuler ces données que de réinterroger la base. Le premier objet de connexion à la base de données aura été créé directement puis initialisé. Les objets suivants seront une copie de celui-ci et donc ne nécessiteront pas de phase d'initialisation.
Structure
modifierPour implémenter ce patron il faut déclarer une classe abstraite spécifiant une méthode virtuelle pure appelée clone(). Toute classe nécessitant un constructeur polymorphique dérivera de cette classe abstraite et implémentera la méthode clone().
Le client de cette classe, au lieu d'écrire du code invoquant directement l'opérateur "new" sur une classe explicitement connue, appellera la méthode clone() sur le prototype ou passera par un mécanisme fourni par un autre patron de conception (par exemple une méthode de fabrique avec un paramètre désignant la classe concrète à instancier).
Le diagramme de classes est le suivant :
La classe Prototype sert de modèle principal pour la création de nouvelles copies. Les classes ConcretePrototype1 et ConcretePrototype2 viennent spécialiser la classe Prototype en venant par exemple modifier certains attributs. La méthode clone() doit retourner une copie de l'objet concerné. Les sous-classes peuvent hériter ou surcharger la méthode clone(). La classe Client va se charger d'appeler les méthodes de clonage via sa méthode operation().
Exemple de code
modifieren C#
modifierpublic enum RecordType
{
Car,
Person
}
/// <summary>
/// Record is the Prototype
/// </summary>
public abstract class Record : ICloneable
{
#region ICloneable Membres
object ICloneable.Clone() { return this.Clone(); }
#endregion
public abstract Record Clone();
}
/// <summary>
/// PersonRecord is the Concrete Prototype
/// </summary>
public class PersonRecord : Record
{
string name;
int age;
public override Record Clone()
{
return (Record)this.MemberwiseClone(); // default shallow copy
}
}
/// <summary>
/// CarRecord is another Concrete Prototype
/// </summary>
public class CarRecord : Record
{
string carname;
Guid id;
public override Record Clone()
{
CarRecord clone = (CarRecord)this.MemberwiseClone(); // default shallow copy
clone.id = Guid.NewGuid(); // always generate new id
return clone;
}
}
/// <summary>
/// RecordFactory is the client
/// </summary>
public class RecordFactory
{
private static Dictionary<RecordType, Record> _prototypes =
new Dictionary<RecordType, Record>();
/// <summary>
/// Constructor
/// </summary>
public RecordFactory()
{
_prototypes.Add(RecordType.Car, new CarRecord());
_prototypes.Add(RecordType.Person, new PersonRecord());
}
/// <summary>
/// The Factory method
/// </summary>
public Record CreateRecord(RecordType type)
{
return _prototypes[type].Clone();
}
}
En JAVA
modifier/* Prototype Class */
public class Cookie implements Cloneable
{
@Override
public Cookie clone()
{
try
{
Cookie copy = (Cookie)super.clone();
// Dans une implémentation réelle de ce patron de conception, il faudrait
// créer la copie en dupliquant les objets contenus et en attribuant des
// valeurs valides (exemple : un nouvel identificateur unique pour la copie).
return copy;
}
catch (CloneNotSupportedException e)
{
return null;
}
}
}
/* Concrete Prototypes to clone */
public class CoconutCookie extends Cookie { }
/* Client Class */
public class CookieMachine
{
private Cookie cookie; // aurait pu être "private Cloneable cookie;"
public CookieMachine(Cookie cookie)
{
this.cookie = cookie;
}
public Cookie makeCookie()
{
return cookie.clone();
}
public static void main(String args[])
{
Cookie tempCookie = null;
Cookie prot = new CoconutCookie();
CookieMachine cm = new CookieMachine(prot);
for (int i=0; i<100; i++)
{
tempCookie = cm.makeCookie();
}
}
}
- (en) Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software, Pearson Education - 1994 (ISBN 9780321700698).
- (en) « Java® Platform, Standard Edition & Java Development Kit Version 21 API Specification », sur docs.oracle.com (consulté le )
- Laurent DEBRAUWER, Design Patterns en Java Descriptions et solutions illustrées en UML 2 et Java (5e édition) - Les 23 modèles de conception, ENI, , 5e éd. (1re éd. 2009), 468 p. (ISBN 9782746050570, présentation en ligne), partie 2, chap. 5 :
« Le pattern Prototype est utilisé dans les domaines suivants : - Un système d’objets doit créer des instances sans connaître la hiérarchie des classes les décrivant. / - Un système d’objets doit créer des instances de classes chargées dynamiquement. / - Le système d’objets doit rester simple et ne pas inclure une hiérarchie parallèle de classes de fabrique. »