Les design patterns

Accueil

Définition

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

Le pattern Observer

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 :

  1. L’armoire
  2. L’horloge

Tous deux peuvent changer d’état:

Voici le code de l’armoire

Accueil.java
La fenêtre principale
L’objet armoire

Les interfaces :

Observateur
Observable

 

Voici le code de l’horloge

Accueil.java
La fenêtre principale (= contrôleur)
Le JPanel d’affichage (= vue)
L’objet horloge (= modèle)

Les interfaces :

Observateur
Observable

Le pattern Modèle - Vue - Contrôleur

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 :

  1. Une qui construit le contrôleur
  2. Une qui construit le modèle qui gèrera l’application
  3. Une qui construit la vue qui l’affichera

Il est abondamment décrit sur le site du zéro.

Le pattern Strategy

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 :

  1. Un qui contient les objets mis en œuvre (guerrier, médecin, civil, …)
  2. Un autre qui contient les comportements

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 :

  1. Le médecin
  2. Le guerrier

Mais on pourrait encore en inventer d’autres
(chirurgien, civil, journaliste)

Les comportements

Interfaces comportementales et classes implémentantes :

Le singleton

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.

Le décorateur

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,
Sur laquelle on rajoute un flux,
Sur laquelle on rajoute un tampon,
Sur lequel on rajoute un sauveur d’objets

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.

La pâtisserie
Le 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();

La classe main

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.

La couche abstraite

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())));