Les modèles de conception sont une manière de concevoir un logiciel.
Ils relèvent essentiellement de l'architecture logicielle.
Nous avons vu le pattern Oberver, le pattern Strategy, le modèle-vue-contrôleur et le singleton
Il permet de découpler les objets.
Par exemple, découpler un objet de l'interface qui l'affiche.
Le couplage d’objets est la relation entre deux objets dont l’un a besoin de l’autre pour être construit.
Par exemple, dans l’objet A, on trouve l’instruction :
B monB = new B();
Il n’est donc pas possible de construire A sans B. Les deux objets sont couplés.
Le couplage pose des problèmes de réutilisabilité.
Chaque objet trimballe avec lui sa cohorte d’objets qui lui sont couplés.
Plus les objets de votre application sont couplés, moins elle est souple et évolutive.
Désormais, avec le pattern Observer, les objets ne se parlent plus directement, mais par l'intermédiaire de leurs interfaces.
Il existe deux sortes d’objets :
Les objets observés possèdent une liste d'observateurs auxquels ils notifient Update losque nécessaire.
Les objets observateurs reçoivent le message update et se mettent à jour en interrogeant l'objet observé sur son nouvel état.
Le pattern Observer dé-couple donc les objets.
Au cours, nous avons construit deux applications observées par leurs interfaces :
Tous deux peuvent changer d’état:
Accueil.java
La fenêtre principale
L’objet armoire
Les interfaces :
Accueil.java
La fenêtre principale (= contrôleur)
Le JPanel d’affichage (= vue)
L’objet horloge (= modèle)
Les interfaces :
Implicitement, nous avons déjà ouvert le pattern suivant, le pattern MVC
Notre horloge consiste, en effet, en un objet aveugle : l'horloge, affiché par un JPanel, le tout sous le contrôle de la fenêtre principale qui gère l’application.
Grâce au pattern observer, nous avons découplé l’horloge de son cadran. Permettant ainsi de l’utiliser dans d’autres contextes.
Le pattern MVC est un des plus puissants en génie logiciel.
Il permet de diviser le travail de conception d’une applicatio en trois équipes de programmeurs :
Il est abondamment décrit sur le site du zéro.
Il s’agit d’éjecter dans des classes les portions de code qui changent.
Ce cours est largement inspiré de l’exemple du site du zéro.
Le pattern strategy a été inventé pour remédier aux limites de l’héritage.
Programmer un comportement (se déplacer, combattre, soigner) dans un objet revient à figer ce comportement dans l’objet, qui ne peut plus en changer.
En outre, il devient difficile de gérer les relations d’héritage par exception et de polymorphisme.
Alors, nous allons externaliser le comportement fluctuant.
L’éjecter dans une classe que nous allons lier dynamiquement è l’objet, qui pourra en plus changer de comportement pendant l’exécution du programme.
L’application que nous avons développé au cours comporte deux packages :
A défaut d’avoir développé une véritable application, nous avons modifié les comportements des personnages dans la méthode main de la classe d'accueil.
Obervez qu’un personnage change dynamiquement de comportement pendant l’exécution du programme.
Les résultats sortent sur la console.
La classe d’accueil
La classe abstraite personnage
Personnage dont héritent :
Mais on pourrait encore en inventer d’autres
(chirurgien, civil, journaliste)
Les comportements
Interfaces comportementales et classes implémentantes :
Un singleton est un objet qui ne peut être instancié qu’une seule fois dans votre application.
Dans la pratique, on l’utilise pour ne générer qu’une seule connexion à une base de données.
La caractéristique majeure du singleton est d’avoir un constructeur privé
Il est donc impossible de l’instancier par l’opérateur new
Pour l’utiliser, il faut le demander au getter statique de la classe.
Exemple de singleton
La classe d’accueil qui l’utilise.
Lorsque nous avons vu les flux, nous avons implicitement mis en œuvre le pattern décorateur.
Il s’agit d’ajouter dynamiquement des fonctionnalités à un objet sans en modifier le code source.
L’exemple que nous avons mis en œuvre provient du site du zéro.
Comme un gâteau qu’on décore couche par couche,
le pattern décorateur permet de décorer un objet en y ajoutant des couches logicielles.
La couche de base est le fichier, |
![]() |
Concrètement, cela donne :
ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream(new File("monFichier.dat"))));
Pour mettre en œuvre le pattern décorateur, vous commencez par la couche de base.
On définit une classe abstraite Pâtisserie, dont on dérive un gâteau.
Ensemble, ils forment déjà quelque chose de fonctionnel.
Créons maintenant une classe principale, contenant la procédure main d’entrée du programme.
On peut déjà y créer un gâteau ainsi :
Patisserie monGateau = new Gateau();
Nous allons maintenant définir ce qu'est une couche.
L’originalité d’une couche est qu’elle EST et qu’elle A une pâtisserie.
Non seulement elle hérite du super-type abstrait,
mais elle en possède une instance qui lui est donnée par constructeur.
Toutes les couches ont donc la même classe-mère.
Voici maintenant quelques exemples de couches concrètes :
La couche de sucre
La couche de fruits
La couche de chocolat
Et pour construire le gâteau avc toutes ses couches, on appelle les constructeurs en les emboîtant comme des poupées russes.
Patisserie monGateau = new CoucheFruits(new CoucheChocolat(new CoucheSucre(new Gateau())));