Design Patterns : Création (Deuxième Partie)
Monteur (Builder)
Intention
Construire un objet complexe étape par étape.
Mise en contexte
Différence avec une fabrique abstraite :
Fabrique abstraite: construire des objets, simples ou complexes, d'une même famille
construire des
Shapes de toutes sortes
Monteur: construire un objet complexe étape par étape.
Construire des
Shapes complexes composées de plusieurs autres formes
Détails
Exemple dans GoF: Labyrinthe.
Créer des labyrinthes étape par étape :
Construire un labyrinthe vide
Ajouter des salles
Ajouter des portes
etc.
Notes:
On pourrait avoir beaucoup plus de méthodes que celles données pour les labyrinthes complexes.
Il faudrait évidemment ajuster les signatures de ces méthodes pour y ajouter des paramètres.
Il n'est pas obligatoire d'avoir une classe et des méthodes abstraites. On pourrait avoir seulement des classes et méthodes concrètes, avec la possibilité d'avoir des méthodes vides au besoin.
Prototype
Intention
Spécifier les types d'objets à créer en utilisant une instance prototype, et créer de nouveaux objets en copiant ce prototype.
Mise en contexte
Application principale: cloner des objets, comme pour un copier-coller.
Détails
Selon les besoins, on peut effectuer une copie en surface ou en profondeur d'un objet prototype.
Copie de surface (shallow copy):
seulement les références aux attributs ou propriétés sont copiés, donc le clone va partager des références aux mêmes objets avec l'objet original (à condition évidemment d'avoir des attributs ou propriétés de type référence dans l'objet)
si les objets partagés sont modifiés, alors l'objet original et ses clones vont voir les modifications
Copie en profondeur (deep copy):
les attributs et propriétés de type référence sont, eux aussi, clonés, donc les références du clone seront vers des objets différents, mais avec le même contenu, que l'objet original
pour une copie en profondeur complète, il faut effectuer une copie en profondeur sur tous les attributs et propriétés de type référence récursivement
En C#, il a différentes façons de cloner des objets
Object.MemberwiseClone(): copie de surfaceICloneable.Clone(): copie de surface ou profonde, selon les besoinsConstructeur de copie :
copie de surface ou profonde, selon les besoins
un constructeur de copie est un constructeur qui accepte un seul paramètre, du même type que la classe
exemple :
public Circle(Circle circle)
Singleton
Intention
S'assurer qu'une classe ne peut avoir qu'une seule instance.
Mise en contexte
Dans certaines applications, il n'est pas logique d'avoir plusieurs instances d'une classe. Comme dans une application avec interface graphique (mobile ou bureau), il n'est souvent pas logique d'avoir plus d'une fenêtre principale.
Dans d'autres applications, il faut s'assurer de bien gérer les resources pour éviter d'avoir des applications trop gourmandes en termes de mémoire ou de processeur ou de réseau ... Comme dans une application qui utilise une base de données, on ne peut avoir qu'un seul pool de connexions à la base de données. Avoir plusieurs pools de connexions serait plus difficile à gérer et consommerait plus de resources.
Ou il faut bien synchroniser l'accès à une resource partagée pour éviter de la corrompre. Les applications avec plusieurs fils d'exécution (avec des thread ou avec des asynch/await) ont normalement besoin de partager certaines structures de données en mémoire, et de synchroniser leur utilisation de ces structures.
Détails
On peut mettre tous les constructeurs d'une classe en mode d'accès privé (ou potentiellement protégé), ce qui empêchera d'autres classes de créer des instances de cette classe.
Ensuite, on ajoute un attribut privé statique pour contenir la référence à l'unique instance
La méthode statique
GetInstancedoit retourner la référence à l'unique instance. La première fois, l'attribut privé statique seranull, donc on devra créer l'unique instance au premier appel deGetInstance, et la placer dans l'attribut prévu à cet effet, avant de retourner la référence à l'unique instance.Alternativement, on pourrait utiliser une propriété avec un getter public qui ferait le même travail de la méthode
GetInstance, et un setter privé qui serait utilisé seulement par le getter lors de sa première utilisation.Une autre option serait d'utiliser un constructeur statique en C#, ou un bloc d'initialisation statique dans d'autres langages.