Design Patterns en Java - PDF

Document Details

Uploaded by Deleted User

Université d'Angers

2024

Olivier Goudet

Tags

Java design patterns software design design patterns programming

Summary

Ce document est un cours sur les design patterns en Java, avec un focus sur le pattern Observateur et le Modèle-Vue-Contrôleur (MVC). Il y a des exemples et des diagrammes de classe.

Full Transcript

Design Patterns en Java Patterns Observateur et Modèle-Vue-Contrôleur (MVC) Olivier Goudet Université d’Angers 10/09/2024 Introduction I Design pattern Observateur (Observer ) : un des patterns les plus uti...

Design Patterns en Java Patterns Observateur et Modèle-Vue-Contrôleur (MVC) Olivier Goudet Université d’Angers 10/09/2024 Introduction I Design pattern Observateur (Observer ) : un des patterns les plus utilisés. I MVC : Modèle-Vue-Contrôleur, un assemblage de patterns qui reprend notamment les patrons de conception Observateur et Stratégie (cf. cours précédent). I Utile pour faire des interfaces utilisateur. I On va en avoir besoin pour le projet. Section 1 Design pattern Observateur Exemple d’application - collecte et affichage de données météorologiques Extrait du chapitre 2 du livre Design Patterns - Tête la première Objectif I Créer une application qui utilise l’objet DonneesMeteo pour actualiser trois affichages différents : 1. un affichage des conditions actuelles 2. un affichage de différentes statistiques météorologiques 3. un affichage de prévisions météo Premier essai d’implémentation public class DonneesMeteo { //Declaration de variables public void changementMesures() { float temp = getTemperature(); float humidite = getHumidite(); float pressure = getPressure(); affichageConditions.actualiser(temp, humidite, pression); affichageStats.actualiser(temp, humidite, pression); affichagePrevisions.actualiser(temp, humidite, pression); } //Autres methodes } Problèmes que l’on rencontre I La classe DonneesMeteo n’est pas fermée à la modification. Elle devra être modifiée par la suite si on souhaite ajouter d’autres types d’affichage. I Nous n’avons aucun moyen d’ajouter ou de supprimer des éléments d’affichage au moment de l’exécution. Design pattern Observateur I Chapitre 2 du livre Design Patterns - Tête la première I Définition : le pattern Observateur définit une relation entre objets de type un-à-plusieurs, de façon que, lorsque un objet change d’état, tous ceux qui en dépendent en soient notifiés et soient mis à jour automatiquement. I Avantage : évite de coupler fortement les objets entre eux. Principe général (cf. page 45 du livre) Diagramme de classes UML simplifié du design pattern Observateur Implémentation de la station météo avec le design pattern Observateur I Qui est l’observable ? I Qui sont les observateurs ? Création de l’interface Observable public interface Observable { public void enregistrerObservateur(Observateur observateur); public void supprimerObservateur(Observateur observer); public void notifierObservateurs(); } Création de l’interface Observateur public interface Observateur { public void actualiser(float temp, float humidite, float pression); } DonneesMeteo est l’observable dans cet exemple public class DonneesMeteo implements Observable{ private List observateurs = new ArrayList(); private float temperature, humidite, pression; public void enregistrerObservateur(Observateur observateur){ observateurs.add(observateur); } public void supprimerObservateur(Observateur observateur){ observateurs.remove(observateur); } public void notifierObservateurs() { for(int i = 0; i< observateurs.size(); i++) { observateurs.get(i).actualiser(this.temperature, this.humidite, this.pression);} } Classe DonneesMeteo (suite) public void setMesures(float temperature, float humidite, float pression) { this.temperature = temperature; this.humidite = humidite; this.pression = pression; notifierObservateurs(); } //Autres methodes } Implémentation d’un premier observateur pour l’affichage des conditions météo public class AffichageConditions implements Observateur{ public AffichageConditions(Observable obs) { obs.enregistrerObservateur(this); } public void actualiser(float temp, float humidite, float pression) { System.out.println(”Conditions actuelles : ” + temp + ” degres et ” + humidite + ” pourcents d humidite”); } } Implémentation d’un deuxième observateur pour l’affichage des prévisions public class AffichagePrevisions implements Observateur{ public AffichagePrevisions(Observable obs) { obs.enregistrerObservateur(this); } public void actualiser(float temp, float humidite, float pression) { System.out.println(”Previsions futures : ” + (temp + pression/ humidite) + ” degres.”); } } Classe de test public class StationMeteo { public static void main(String[] args) { DonneesMeteo donneesMeteo = new DonneesMeteo(); AffichageConditions affichageConditions = new AffichageConditions(donneesMeteo); AffichagePrevisions affichagePrevisions = new AffichagePrevisions(donneesMeteo); donneesMeteo.setMesures(35, 22, 5); donneesMeteo.setMesures(28, 55, 2); } } Sorties Console Console Conditions actuelles : 35.0 degres et 22.0 pourcents d’humidite Previsions futures : 35.227272 degres. Conditions actuelles : 28.0 degres et 55.0 pourcents d’humidite Previsions futures : 28.036364 degres. Diagramme de classes UML simplifié du programme Utiliser directement l’API Observer de Java import java.util.Observable; public class DonneesMeteo extends Observable{ private float temperature, humidite, pression; public void setMesures(float temperature, float humidite, float pression) { this.temperature = temperature; this.humidite = humidite; this.pression = pression; setChanged(); notifyObservers(); } public float getTemperature() {return temperature;} public float getHumidite() {return humidite;} public float getPression() {return pression;} } Implémentation de l’affichage des conditions météo import java.util.Observable; import java.util.Observer; public class AffichageConditions implements Observer{ public AffichageConditions(Observable obs) { obs.addObserver(this); } public void update(Observable o, Object arg) { DonneesMeteo donneesMeteo = (DonneesMeteo)o; System.out.println(”Conditions actuelles : ” + donneesMeteo. getTemperature() + ” degres et ” + donneesMeteo. getHumidite() + ” pourcents d humidite”); } } Implémentation de l’affichage des prévisions météo import java.util.Observable; import java.util.Observer; public class AffichagePrevisions implements Observer{ public AffichagePrevisions(Observable obs) { obs.addObserver(this); } public void update(Observable o, Object arg) { DonneesMeteo donneesMeteo = (DonneesMeteo)o; System.out.println(”Previsions futures : ” + (donneesMeteo. getTemperature() + donneesMeteo.getPression()/ donneesMeteo.getHumidite()) + ” degres.”); } } Le test est le même public class StationMeteo { public static void main(String[] args) { DonneesMeteo donneesMeteo = new DonneesMeteo(); AffichageConditions affichageConditions = new AffichageConditions(donneesMeteo); AffichagePrevisions affichagePrevisions = new AffichagePrevisions(donneesMeteo); donneesMeteo.setMesures(35, 22, 5); donneesMeteo.setMesures(28, 55, 2); } } Diagramme de classes UML simplifié avec l’API java.util.Observer Pour aller plus loin. Une API plus récente pour implémenter des observateurs en Java. I Utilisation des API PropertyChangeSupport et PropertyChangeListener. I De plus en plus utilisées par rapport à l’API Observer qui est deprecated depuis Java 9. I Permet de spécifier aux observateurs ce qui a changé dans l’observable. I Les observateurs peuvent être notifiés seulement si certains changements spécifiques se produisent dans l’observable. I Voir l’exemple de code sur Moodle. Section 2 Modèle-Vue-Contrôleur Modèle-Vue-Contrôleur (MVC) I Un exemple est donné à partir de la page 529 du livre Design Patterns - Tête la première. I Implémentation d’un MVC dans le projet Pacman pour gérer les liens dynamiques entre la vue du jeu, l’interface utilisateur et l’état du jeu. Vue d’ensemble du MVC Utilisation du pattern Observateur Utilisation du pattern Stratégie Exemple d’implémentation I On souhaite définir l’état d’un jeu qui contient différentes variables comme le nombre de joueurs, le nombre de tours joués, etc. I On veut définir une interface utilisateur qui offre des commandes pour initialiser le jeu et effectuer un tour de jeu. I L’interface doit permettre aussi de visualiser le nouvel état du jeu après chaque action de l’utilisateur. Conception du programme Implémentation de la classe Game (le modèle dans MVC), c’est un sujet observable public class Game extends Observable{ private int turn; private int maxturn; private int nbPlayers; private boolean isOver; public Game(int nbPlayers, int maxturn) { this.nbPlayers = nbPlayers; this.maxturn = maxturn; } classe Game (suite) public void init() { this.turn = 0; this.setChanged(); notifyObservers(); } public void incrementTurn() { turn++; this.setChanged(); notifyObservers(); } public void run() { while(turn < maxturn) { incrementTurn(); } this.isOver = true; this.setChanged(); notifyObservers(); } } Implémentation de l’interface utilisateur (la vue dans le MVC), c’est un observateur. public class VisualInterface implements Observer{ InterfaceController controller; JFrame frame;... public VisualInterface(InterfaceController controller, Observable game) { this.controller = controller; game.addObserver(this); this.createUserFrame(); } public void update(Observable obs, Object arg) { Game game = (Game)obs; System.out.println(”Turn : ” + game.getTurn()); } public void createUserFrame() {...} } Définition d’une stratégie de contrôle pour l’interface utilisateur (Stratégie abstraite) public interface InterfaceController { public void run(); public void reinit(); } Implémentation d’un premier contrôleur (Stratégie concrète) public class Controller1 implements InterfaceController { private Game game; public Controller1(Game gameState) { VisualInterface view = new VisualInterface(this, gameState); this.game = gameState; } public void run() { this.game.run(); } public void reinit() { this.game.init(); } } On peut avoir autre type de contrôleur public class Controller2 implements InterfaceController{ private Game game; public Controller2(Game game) { VisualInterface view = new VisualInterface(this, game); this.game = game; } public void run() { for(int i = 0; i < 5; i++) { this.game.step(); } } public void reinit() { this.game.init(); } } Lancement du programme public class Main { public static void main(String[] args) { Game game = new Game(2,10); Controller1 controller1 = new Controller1(game); // Ou bien avec un autre controleur Controller2 controller2 = new Controller2(game); } }

Use Quizgecko on...
Browser
Browser