Mis à jour 22/05/2025
Design Patterns
Patterns créateurs (Singleton, factory, abstract factory)
Patterns aidant à la gestion de la création d’objet
Patterns structurants (Façade, proxy, decorator, composite, adapter)
On parle de travailler sur la partie externe des classes du pattern. L’extensibilité et l’encapsulation des classes.
Patterns comportementaux (Strategy, iterator, observer, state)
Ici, on travaille sur la partie interne des classes du pattern. La dynamique des classes du pattern. Améliorer la qualité du code, éviter les duplications ou gérer des problématiques connues.
Principe n°1
Principe n°2
Principe n°3
Rappel de certaines notions objets importantes
La mise en place de Design Pattern va nécessiter des notions objets simples mais importante pour la compréhension de ces derniers. Nous allons revoir rapidement :
L'héritage permet de partager des propriétés et méthodes entre les classes, il suffit d'utiliser le mot clé extends pour que cette classe (fille) hérite de la classe de base (mère).
Le partage de code s'effectue de manière descendante uniquement.
Classe mère
Classe fille
Instanciation
Attention ici !
On peut utiliser les propriétés et méthodes de la mère et de la fille grâce à l'héritage
Le but de cet exemple est de mettre en place de l'héritage pour un "Animal". Les classes pouvant en hérité sont "Hibou", "Dragon" et "Tigre".
Animal
Hibou
Dragon
Tigre
Classe mère
Classes filles
Instanciation
Chaque animal a sa
propre définition de walk, sauf le tigre qui marche normalement.
Note : new permet de redéfinir la méthode mère
Certains mots clés sont à connaître pour l'héritage :
Réaliser de l'héritage
Cette fois-ci, vous devez réaliser de l'héritage entre une classe mère "Personne" et deux classes filles "Etudiant" et "Formateur".
La personne a un nom et un prénom + constructeur
Le formateur a un sujet à traiter + constructeur & appel du constructeur parent
L'étudiant a une note + constructeur & appel du constructeur parent
Chaque classe fille possèdera donc 3 propriétés public et peuvent les setter à leur convenance.
Réalisez les classes et le Program.cs permettant d'implémenter cet héritage et appelez les propriétés inline pour réaliser des Console.WriteLine() des 3 propriétés pour le Formateur et pour l'Etudiant.
PS : Pas besoin que le formateur puisse modifier la note de l'étudiant, il suffit juste que vos différentes classes filles aient leurs propres ajouts de méthodes par rapport aux propriétés demandées.
Les interfaces sont à considérer comme des contrats à respecter, elles contiennent des propriétés et des signatures de méthodes qui seront à implémenter dans la classe héritant de cette interface
Contient une propriété et une méthode qui devra être redéfinie dans les classes implémentant
Contient une propriété et une méthode qui devra être redéfinie dans les classes implémentant
Ici, Cat doit forcément avoir une propriété Name et une méthode MakeSound qui respectent le contrat de l'interface
Une association traduit un lien entre une classe A et une classe B (appel de méthode par exemple).
L'agrégation est une association particulière : l'objet A possède une ou plusieurs instances de B.
Instanciation
Program.cs
Une composition est une agrégation particulière : toutes les instances de B contenues dans A sont supprimées lorsque A est supprimée.
Autre exemple plus complexe (pour revoir un peu d'orienté objet supplémentaire)
Instanciation
Exercice Orienté Objet
Réaliser une agrégation entre Author et Book.
Une classe abstraite (mère) permet de définir les signatures des méthodes et les propriétés qui seront partagés à la classe qui va étendre cette classe abstraite (fille)
L'intérêt principal des classes abstraites est d’informer l’utilisateur (la classe fille) de cette classe qu’une instance de cette dernière n’a pas d’utilité a être instanciée. Exemple : vous devez gérer un centre de location de véhicules (voiture, camion, vélo ….). Vous avez très certainement une classe Vehicule, dont héritera Velo, Voiture, Camion…
Mais le centre de location n'aura jamais besoin d'instancier un Vehicule.
Les classes abstraites peuvent également posséder des méthodes abstraites. Ce sont des méthodes qui ne possèdent pas de corps, et qui devront obligatoirement être surchargée par les classes qui en hérite
Un autre exemple pour mieux comprendre... Nous avons une classe abstraite Shape et deux classes filles Square & Circle.
Impossible
d'instancier une forme,
Shape est un concept abstrait
Hérite de Shape
Ce qui lui en donne les propriétés & force à redéfinir "Draw"
Exercice Orienté Objet
Réaliser une abstraction entre une classe Fruit et deux classes Orange, Fraise
A noter : La classe Fruit ne doit pas pouvoir être instanciée.
Les trois éléments sont utilisées pour réaliser de la réutilisation de code descendante :
Définir une dépendance entre un objet observé et un ou plusieurs objets observants.
L’objectif étant de pouvoir notifier les objets observants lorsqu’un changement de statut est opéré sur l’objet observé.
On a parfois besoin de connaître le changement de statut d’un autre objet. Il est possible d’interroger l’objet en continue pour connaître son statut et le mettre à jour si nécessaire.
Ceci est très gourmand s’il y’a plusieurs abonnés et surtout si on interroge toutes les secondes, alors que le statut change de manière aléatoire ?
Ceci n’est pas efficace.
Text
update(ConcreteSuject sub);
Eviter les opérations de PULL massives et simplement effectuer un push / pull lorsque c’est nécessaire.
Plus concrètement, améliorer la logique métier
Diminuer le coûts de l’observation
Supprimer la question de l’intervalle d’interrogation
Exercice (Réaliser un pattern Observer)
Reprenez le pattern Observer pour observer la modification d'une température et notifier des objets observants ce changement de température.
Chaque modification de température affiche (dans la console) la nouvelle température pour tous les objets observants.
Pensez bien à avoir plusieurs observants.
Développez le code du pattern en C#
L'idée principale est de pouvoir mettre en place une certaine stratégie ou ce que l’on va régulièrement appeler un comportement afin de pouvoir en changer dynamiquement au runtime.
Sans pattern stratégie, on serait obligé de multiplier les classes en produit cartésien pour pouvoir avoir autant de combinaisons de comportements que nécessaire. (Horrible)
L’héritage est puissant mais il ne permet de partager du code que de manière verticale, c’est-à-dire à ses enfants.
Par contre, si les enfants veulent partager du code entre eux, aucun moyen de le faire à part en dupliquant le code (Horrible).
Meilleure lisibilité du code. (Pas de duplication, pas de gros pavés de méthodes dans une seule classe)
S’assurer que chaque élément à sa propre responsabilité (découplage fort)
Et surtout avoir des comportements interchangeables au runtime sans avoir à multiplier les classes.
Exercice (Réaliser un pattern Strategy)
Reprenez le pattern Stratégie pour l’appliquer à ce sujet :
Une interface StrategieInterface ayant pour contrat function reagir(PersonneInterface $personne);
Quatre classes (Enerve, Geek, Jovial, Sad) chacune implémentant StrategieInterface et redéfinissant donc la méthode réagir:
Une interface PersonneInteface ayant pour contrat function donnerPhrase();
Une classe Personne qui implémente PersonneInterface et donc redéfini donnerPhrase :
Une classe Contexte qui a une stratégie en propriété.
Développez le code C# correspondant
Reaction.React(phrase)
Console.WriteLine(...)
Exercice (Réaliser un pattern Strategy)
Reprenez le pattern Stratégie pour l’appliquer à ce sujet :
Développez le code C# correspondant
Comme son nom l’indique, il a pour objectif de rendre une interface non adaptée à une autre, compatible. En rajoutant un objet intermédiaire nommé « Adapter ».
Les interfaces exposées ne sont pas toujours compatibles avec ce que nous avons, il nous faut donc réaliser une adaptation intermédiaire pour pouvoir coupler les deux.
Comment appliquer l'adapter à ce problème ?
Adapter une interface pour qu’elle s’imbrique dans une autre, tout simplement.
Découplage fort
Peut-être facilement mis en place même après coup, à moindre coût
Exercice (Réaliser un pattern Adapter)
Je vous ai envoyé un code avec un nouveau système et un ancien système, votre objectif est de mettre en place l'adapter afin de pouvoir faire fonctionner conjointement l'ancien et le nouveau système pour le client qui utilise ce système.
Développez le code du pattern en C#
Exercice (Réaliser un pattern Adapter)
Je vais vous envoyer le code que vous devez adapter pour pouvoir permettre à votre classe cliente (ThirdPartyBillingSystem) d'afficher les employés d'une manière plus propre et ordonnée et correspondre au ClassicCase en List<string>.
Vous devez implémenter une classe
class EmployeeAdapter : HRSystem, ITargetBis.
(Vous pouvez enlever le Bis de ITargetBis, c'est l'interface utilisée) qui appelle GetEmployees afin de retourner une liste d'employé pour adapter l'affichage comme demandé.
Développez le code du pattern en C#
Résultat attendu :
Le pattern singleton est le plus simple des patterns, il permet de s’assurer qu’un objet est instancier qu’une et une seule fois dans toute votre application.
Ce sera toujours la MÊME instance de l’objet quelque soit depuis quel endroit l’objet est appelé.
On instancie un objet quelque part, on y fait des opérations dessus, puis on souhaite à nouveau réutiliser cet objet à un autre endroit.
Pour que les opérations soient gardées en mémoire, on ne peut pas le faire, car on devra réinstancier la classe puis réeffectuer les opérations dessus. (Ou alors rajouter des dépendances inutiles)
S’assurer qu’un objet est instancier qu’une seule fois et y avoir accès facilement depuis n’importe où dans votre application.
Certains estiment que le pattern singleton est un mauvais pattern (à ne pas confondre avec anti-pattern). Pour deux raisons, à ma connaissance :
1. Le pattern singleton est utilisable uniquement en statique, les débats sont nombreux avec tout ce qui tourne autour du mot clé « static ». Je vous laisserai vous renseigner et vous faire votre propre opinion, mais sachez que pour ma part, je l’utilise très fréquemment.
2. D’après certains développeurs, le fait de dire qu’on est certain que l’on veut une seule instance de son objet à tout jamais dans son application n’est pas en lien avec le fait de faire de son application une application évolutive à toute épreuve.
Pour eux, afin que ça reste évolutif, on ne peut pas se limiter à une seule instanciation. Habituellement, l'autre possibilité est d'utiliser une Factory.
Je comprends le point de vue, mais je n’y adhère pas. J’utilise fréquemment le singleton pour instancier ma base de données par exemple. Dans 99,99% des cas, je sais à l’avance que je n’aurai qu’une instance de base de données et ceci n’évoluera pas au fil du temps.
Réalisez un pattern Singleton sur un objet President, qui a un nom. Par défaut le nom du président est "Undefined" (ça peut être initialiser dans le constructeur privé). Et qui peut changer de nom. Quelque soit l'endroit où est appelé cet objet President, ce sera toujours le même qui sera appelé. Réalisez une méthode d'affichage du nom du président, exemple : DisplayPresident() qui affiche le nom du président dans un Console.WriteLine.
L'objectif était de simuler l'appel de cet objet depuis plusieurs fichiers comme fait dans l'exemple que l'on a fait ensemble.
Réalisez le code en C# pour implémenter ce pattern
Permet d’ajouter dynamiquement des propriétés à un objet.
En pouvant empiler/décorer avec autant d’objets décorable que l’on souhaite.
L’objet décoré et le ou les objets décorants s’utilisent de la même façon, excepté que la plupart du temps, les objets décorants ne peuvent pas exister sans objet à décorer.
Duplication de code et multiplication des classes pour gérer toutes les possibilités (inutiles).
Simple à mettre en place
Evite la multiplication des classes
Permet d’ajouter des caractéristiques multiples sans limite (excepté celles définies par l’interface) à un objet de base.
Le fait d’envelopper permet de facilement exécuter des opérations qui sont à effectuer sur chaque enveloppe pour en avoir un résultat global (prix d’une boisson par exemple)
Attention, ça ne permet pas de connaître l'ordre de décoration !!!
Adaptez le diagramme vu ensemble en utilisant la problématique suivante :
On a une boisson de plusieurs type : café, chocolat au lait, thé, …
Chaque boisson peut avoir plusieurs décorations : sucre, caramel, chocolat,…
L'objectif est de calculer le prix à la compilation en fonction de la décoration
Réalisez le code en C# permettant de mettre ceci en œuvre
Décorez un café avec deux fois du caramel et une fois du sucre, par exemple.
Adaptez le diagramme vu ensemble en utilisant la problématique suivante :
On a une pizza de deux trois types possibles : base crème, base tomate, chausson
Chaque pizza peut avoir plusieurs décorations : champignons, oeufs, oignon, jambon,... (à vous de mettre ce que vous voulez sur votre pizza)
L'objectif est de calculer le prix à la compilation en fonction de la décoration
Réalisez le code en C# permettant de mettre ceci en œuvre
Décorez une pizza afin de réaliser votre pizza favorite
Permet de gérer des états sur des objets tout en gardant la flexibilité d’opérer toutes les actions que voulues sur chaque état.
Sans avoir à enchainer les if (x.state === State.closed) {…}.
On change le state d’un objet et c’est ce state s’auto-gère en fonction des opérations qui sont proposées par l’interface State.
La gestion d’état sur des objets est gérable avec de simples conditions, mais dans le cas où l’on a beaucoup d’état qui peuvent changer en fonction de différentes opérations, le code devient une succession de condition.
D’une part, c’est incompréhensible à premier abord (surtout sans commentaire, ça peut prendre un certain temps) et d’autre part, lorsque l’on veut ajouter un state ou une opération on se retrouve a devoir modifier tout ça au risque de tout péter.
Exercice (Réaliser un pattern State)
Réalisez le code permettant d'implémenter un pattern State répondant aux besoins précisés par le diagramme d'états transitions envoyé.
(Débutant, confirmé, expert, indétrônable, en pouvant sauter des niveaux que ce soit positivement ou non. Excepté quand on arrive à indétrônable)
Développez le code du pattern en C# pour implémenter cette problématique d'états.
Exercice (Réaliser un pattern State)
Si nous avons assez de temps, je vais vous demander de réaliser un pattern State, l’idée ici est de gérer les statut d’une porte :
Réalisez le code C# associé à ce pattern
C’est sensiblement la même chose que le pattern façade, excepté que le pattern proxy exprime un but précis lors du passage par le proxy.
3 types de proxys peuvent être utilisés :
J’insiste sur le fait que c’est plus une vision UML différente qu’une implémentation dans le code différente.
Appel d’un composant externe qui nécessite un accès sécurisé, par exemple
Exercice (Réaliser un pattern Proxy)
Je vous demande de réaliser un pattern proxy, par exemple en utilisant le proxy pour valider un token d’authentification simple (un simple « toto » == « toto » suffit).
Pour ceux qui veulent développer un peu je propose de générer un fichier "Bonjour.txt" contenant 500 000 lignes d'enchaînement de mots générées aléatoirement, ou trouvez une idée d'opération couteuse à effectuer, je suis preneur de bonnes idées.
Réalisez le code C# du pattern proposé
Le pattern façade permet de gérer les multiples dépendances de manière regroupée dans une classe façade qui va nous permettre de définir un certain nombre de dépendances / instanciations à notre place.
Il peut également être utilisé comme gestionnaire de méthodes !
Dans nos codes, les références à d’autres objets sont multiples et fréquentes. Parfois, il devient difficile ou pénible de devoir instancier les 10 objets dont dépendent l’objet que l’on souhaite.
Exercice (Réaliser un pattern Façade)
Réaliser un pattern façade, l'idée est de mettre en place une façade qui va gérer pour nous l'instanciation de sous classes.
Réalisez le diagramme UML + le code d'implémentation
Mettez de côté vos design pattern dans un dossier en nommant le fichier avec le nom du pattern. Vous m'enverrez un zip avec tous les patterns à la fin de la formation. J'utiliserai ça pour la notation.
Le pattern command a pour objectif d’encapsuler une requête pour la rendre accessible depuis n’importe quel récepteur et la permettre d’être envoyée depuis n’importe quel émetteur.
L’idée est d’également de s’ajouter la possibilité de « undo » les commandes facilement. (Si en utilisation avec le pattern composite, on peut même effectuer des macro commandes qui exécute plusieurs petites commandes, sans en rendre plus compliqué le undo).
Comment proposer un service d’exécution de requêtes à de multiples clients / sujets ?
Comment s’assurer que l’on nous demande pas d’exécuter quelque chose que l’on ne sait pas traiter ?
De manière générale, comment gérer la commande ? et l'inverser ?
Actions
Exercice (Réaliser un pattern Command)
Reprenez le pattern Command pour l’appliquer à ce sujet : Gestion du son, pour l’augmenter et le baisser. L’idée va être d’avoir une ICommand qui va pouvoir execute, unexecute une action.
Cette action est définie dans une classe Receiver.
L’Invoker va lui contenir les Command, ainsi que deux méthodes:
Faites deux Invoker(Remote, Voice) différents et deux Receiver différents (HiFiSystem, TV)
Réalisez le code C# du pattern proposé
C’est simple, c’est un pont.
Un pont entre une classe abstraite et une interface permettant d’anticiper le problème de multiplication de classe vu dans le pattern adapter.
L’idée pour différencier les deux, concrètement, c’est que l’adapter corrige un problème de compatibilité alors que le pont l’anticipe pour ne jamais avoir le problème.
Deux interfaces ne sont pas forcément compatibles si elles n’ont pas été pensées au départ pour l’être.
La gestion d’un produit cartésien de nos classes nécessite la multiplication des classes, pour un 3x3, le gain est de 3 classes, mais pour du 20x20, le gain est élevé.
Exercice (Réaliser un pattern Bridge)
Réaliser un pattern bridge, l’idée est de faire un bridge pour pouvoir lier une clé de voiture avec une clé de maison, ou une clé de garage par exemple :
(J'ai un autre exercice si celui-ci ne vous parle pas trop)
Réalisez le code C# d'implémentation du pattern
Le pattern factory a pour objectif de gérer la construction d’objet différemment qu’avec un « new ».
C’est la factory qui s’assure de la création / suppression de ces objets.
En général, une factory est utilisée lorsque l’on souhaite gérer la façon dont sont créer les objets via des méthodes (Par exemple, RandomCarFactory et RegularCarFactory)
On veut parfois ne pas avoir à gérer via le client quel type d’objet sera créer. Ou alors, on souhaite gérer un ordre de création d’objet ou pouvoir le modifier à la volée (par exemple createMutableObject ou createImmutableObject)
Exercice (Réaliser un pattern Factory simple)
Réaliser un pattern Factory afin de pouvoir gérer la création de véhicules différemment à la volée dans le code. Vous allez implémenter :
A noter : Il n'est pas nécessaire de développer un vrai random pour cet exercice (mais ça rajoute un peu de code alors pourquoi pas !)
Optionnel : Faites une classe qui génère des voitures suivant la suite de Fibonacci. Donc, 1 Renault, 1 Audi, 2 Mercedes, 3 Renault, 5 Audi, 8 Mercedes, 13 Renault,...
Réalisez le diagramme UML + le code d'implémentation
Mettez de côté vos design pattern dans un dossier en nommant le fichier avec le nom du pattern. Vous m'enverrez un zip avec tous les patterns à la fin de la formation. J'utiliserai ça pour la notation.
Le pattern Abstract Factory a le même objectif que le Factory Method. Mais il permet de pouvoir gérer des objets interdépendants en s'assurant d'une compatibilité entre eux.
L'objectif est de créer un ensemble d'objets qui ont pour objectif d'être utilisés ensemble.
Comment ajouter la possibilité de gérer des objets interdépendants au Factory Method ?
Exercice (Réaliser un pattern Abstract Factory)
Le but de l'exercice est d'implémenter une Abstract Factory pour gérer une interface graphique utilisateur qui peut produire différent styles de boutons et de checkboxes (Windows / MacOS)
Réalisez le diagramme UML + le code d'implémentation
L'UML se trouve sur la page suivante !
Exercice de refactoring guru
Exercice (Réaliser un pattern Abstract Factory)
Exercice de refactoring guru
Exercice de refactoring guru
Ce pattern propose une manière de gérer la composition d’objets qui contiennent des objets en arbre.
C’est-à-dire qu’un objet est composé d’un autre objet, qui peut être composé de plusieurs autres objets, etc…
On souhaite pouvoir utiliser les mêmes méthodes que l’on soit dans un nœud composite ou dans un nœud composant.
Comment gérer de la récursivité de manière transparente pour le code utilisateur entre objet, sans utiliser de conditionnel sur le type de l’objet ?
I
Exercice (Réaliser un pattern Composite)
Réaliser un pattern composite, l'idée est de pouvoir construire une arborescence de <ul> et de <li> imbriqués grâce au pattern composite. Il vous faut :
Réalisez le diagramme UML + le code d'implémentation
Mettez de côté vos design pattern dans un dossier en nommant le fichier avec le nom du pattern. Vous m'enverrez un zip avec tous les patterns à la fin de la formation. J'utiliserai ça pour la notation.
Ici, l’objectif est de pouvoir parcourir une liste d’objets d’une manière algorithmique implémentée manuellement.
Aujourd’hui ça semble inutile comme pattern, car on a des structures qui utilise ce pattern pour nous. (ArrayList, List, Map, etc…) Tout ce qui est IEnumerable, en gros (IEnumerable c’est notre Iterator) avec les petites surcouches en LinQ qui vont bien…
Mais ça peut arriver que ceci ne soit pas disponible.
Gestion d’un ensemble d’objet sans avoir accès à des types qui permettent d’itérer sur la liste.
Exercice (Réaliser un pattern Iterator)
Réaliser un pattern Iterator, ici l'objectif est de mettre en place un iterateur pour lister une collection d'items (WordsCollection implements \IteratorAggregate) en AlphabeticalOrderIterator (implements \Iterator) permettant de lister les items de collection.
A noter que PHP met déjà en place pour vous les interface Iterator & IteratorAggregate.
Vous devez donc :
Réalisez le diagramme UML + le code d'implémentation
Mettez de côté vos design pattern dans un dossier en nommant le fichier avec le nom du pattern. Vous m'enverrez un zip avec tous les patterns à la fin de la formation. J'utiliserai ça pour la notation.
Exercice difficile
L'objectif de ce pattern est de mettre en place une abstraction de construction d'objets complexes.
Afin qu'un client puisse créer ces objets sans avoir à se soucier de la complexité de création.
Comment gérer la construction d'objets complexes sans connaitre leur implémentation ?
Comment simplifier l'utilisation de votre code si ces objets complexes ont plusieurs implémentations et représentations ?
Implémenter le pattern builder afin de gérer la construction de maisons différentes en étape par étape.
Le but du pattern est la création de nouveaux objets par duplication d’objets existants appelés prototypes qui disposent de la capacité de clonage.
Comment générer un clone d'un objet efficacement ?
Ce pattern a pour objectif de partager de façon efficace un ensemble de petits objets.
Souvent utilisé pour ajouter des comportements dynamiques à un objet englobant.
(Ex : Une voiture et toutes les options sélectionnées)
Comment gérer efficacement des associations entre de nombreux petits objets dynamiques et un objet parent ?
Comment s'assurer que l'option ajoutée fait déjà partie de la liste des options déjà crées ?
Le pattern Chain of Responsibility construit une chaîne d’objets telle que si un objet de la chaîne ne peut pas répondre à une requête, il puisse la transmettre à son successeur et ainsi de suite jusqu’à ce que l’un des objets de la chaîne y réponde.
Ex : Plusieurs moyens de paiement ou plusieurs instances de serveur pour exécuter une requête
Comment avoir plusieurs objets répondant à un critère et permettre l'utilisation en chaîne (si possible pour l'objet) d'objets, afin d'utiliser le premier objet qui peut répondre à ce critère à un moment T ?
Son objectif est très souvent associée à la mise en place d'arbres syntaxiques, permettant par exemple de construire un moteur de recherche avec des options de recherche selon les critères retrouvés.
Comment gérer un arbre syntaxique généré dynamiquement sous formes d'objets maîtrisés ?
Comme son nom l'indique, ce pattern a pour objectif de construire un objet intermédiaire qui gère les possibilités d'interactions entre deux objets, sans que ces deux derniers n'aient à se connaître.
Comment gérer l'interaction complexes entre un sous ensemble d'objets qui n'ont pas connaissance les uns des autres ?
Son but est de sauvegarder et de restaurer l’état d’un objet sans oublier le principe d'encapsulation.
On l'utilise en général afin de pouvoir gérer les incompatibilités associés à des changements d'états. Par ex : Gestion des incompatibilités suite au choix des options sur une voiture
Comment gérer les changements d'états afin de pouvoir revenir en arrière ?
Comment revenir en arrière sur des incompatibilités entre objets / options ?
Le pattern Template Method permet de reporter dans des sous-classes certaines étapes de l’une des opérations d’un objet, ces étapes étant alors décrites dans les sous-classes.
Plus simplement, il permet de factoriser une étape commune dans une classe afin d'éviter la duplication de code.
Comment éviter la duplication de code induite lorsqu'une opération complexe comprend plusieurs représentations en plusieurs étapes, dont certaines sont identiques ?
Le pattern Visitor construit une opération à réaliser sur les éléments d’un ensemble d’objets. De nouvelles opérations peuvent ainsi être ajoutées sans modifier les classes de ces objets.
Comment ajouter plusieurs opérations à des objets sans avoir à les modifier ?
Design Patterns
Petite attention particulière sur la surutilisation : même quand vous aurez l’habitude d’utiliser les design patterns…
Le but des patterns est de répondre à une problématique de code par une conception adaptée ET PAS rendre la conception plus complexe pour mettre des patterns juste parce qu’on veut absolument mettre des patterns partout.
C’est assez effrayant le nombre de développeurs en entreprise qui font ça, de mon expérience, je dirai qu’environ 10% des développeurs que j’ai connu avaient ce syndrome. Travailler avec eux était d’autant plus compliqué que leur syndrome était avancé !
Car ils ajoutent une complexité non négligeable à un projet et ensuite pour faire intervenir une ressource non expérimentée et bien… ça fini souvent avec quelqu'un en pleure avant même d’avoir écrit une ligne de code.
Pour appuyer mes propos, imaginez, nous avons vu une architecture MVC (en 3 couches), y ajouter des patterns n’est déjà pas toujours évident, même si les patterns que l’on a vu s’adaptent bien à l’architecture MVC.
D’autres architectures existent, par exemple SOA, qui est une architecture orientée services. Cette architecture contient, en moyenne pour une utilisation normale, entre 10 et 12 couches. Là, on parle d’une complexité déjà impactante en termes d’architecture…
Ajoutez une surutilisation de patterns et seuls les développeurs séniors seront capables de travailler sur ce projet (mais ça ne donnera envie à personne…)
Evitez absolument la complexité dans vos développements, un pattern n'a d'avantage que s'il est employé correctement
BON COURAGE !
Workshop Design Pattern
Ce workshop va vous faire pratiquer l'ensemble des patterns dans un domaine donné.
L'objectif est de réaliser le maximum de patterns.
L'exercice n'est pas si simple, mais en avançant doucement mais sûrement, vous y arriverez !
N'hésitez pas à me poser des questions.
Les patterns les plus simples :