package com.llgc; import com.llgc.ctrl.CtrlNombre; import com.llgc.modele.MdlNombre; import com.llgc.vue.Fenetre; public class Main { public static void main(String[] args) { // Instanciation de notre modèle // Le modèle n'est lié à aucune information. MdlNombre nombre = new MdlNombre(0); // Création du contrôleur // Le contrôleur doit savoir quel objet il contrôle. CtrlNombre ctrl = new CtrlNombre(nombre); // Création de notre fenêtre avec le contrôleur en paramètre // La fenêtre est obligatoirement liée au contrôleur. Fenetre fenetre = new Fenetre(ctrl); // Ajout de la fenêtre comme observeur de notre modèle nombre.addObserver(fenetre); } } package com.llgc.modele; import java.util.EnumSet; import java.util.Observable; // Le modèle est observable par les vues. public class MdlNombre extends Observable { private int nombre; public synchronized int getNombre() { return nombre; } public synchronized void setNombre(int nombre) { this.nombre = nombre; setChanged(ChangeNombre.NOMBRE); notifyObservers(changeEnum); changeEnum = EnumSet.noneOf(ChangeNombre.class); } public MdlNombre(int nombre) { super(); this.nombre = nombre; // Initialisation de l'énumération des modifications à vide. changeEnum = EnumSet.noneOf(ChangeNombre.class); } // Pour se souvenir quelles propriétés ont été modifiées (si besoin). public enum ChangeNombre { NOMBRE; } private EnumSet changeEnum; // setChanged est mis en synchronized car il l'est dans Observable. protected synchronized void setChanged(ChangeNombre changeEnum_) { setChanged(); changeEnum.add(changeEnum_); } } package com.llgc.ctrl; import com.llgc.modele.MdlNombre; public class CtrlNombre { private MdlNombre nombre; // Le contrôleur surveille le modèle Nombre. public CtrlNombre(MdlNombre nombre) { super(); this.nombre = nombre; } // Méthode validant les demandes de modifications de l'IHM. public Boolean setNombre(String nbStr) { try { nombre.setNombre(Integer.parseInt(nbStr)); return true; } catch (NumberFormatException e) { return false; } } } package com.llgc.vue; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.util.EnumSet; import java.util.Observable; import java.util.Observer; import javax.swing.AbstractAction; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTextField; import com.llgc.ctrl.CtrlNombre; import com.llgc.modele.MdlNombre; import com.llgc.modele.MdlNombre.ChangeNombre; public class Fenetre extends JFrame implements Observer { private static final long serialVersionUID = 2474983998400143732L; private CtrlNombre ctrl; private JTextField bt; // La fenêtre communique au contrôleur les modifications. public Fenetre(CtrlNombre ctrl) { super(); this.ctrl = ctrl; // IHM ultra simple. getContentPane().setLayout(new BorderLayout()); JPanel pnl2 = new JPanel(); pnl2.add(new JButton(new ActionChangeNombre("Modifier"))); bt = new JTextField(25); pnl2.add(bt); getContentPane().add(pnl2); pack(); setVisible(true); } // Informations reçues de la part du modèle @Override public void update(Observable o, Object arg) { if (o instanceof MdlNombre) { MdlNombre nb = (MdlNombre)o; // Il n'est pas possible de caster un Object vers un EnumSet sans warning. @SuppressWarnings("unchecked") EnumSet cg = (EnumSet)arg; // Traitement des modifications. // Ici, on se contente d'afficher les modif dans la console. System.out.println(nb.getNombre()); for (ChangeNombre iterable_element : cg) { System.out.println(iterable_element.toString()); } } } // Événement associé au bouton changeant la valeur du nombre. private class ActionChangeNombre extends AbstractAction { private static final long serialVersionUID = 4927921822320583419L; public ActionChangeNombre(String name) { super(name); } @Override public void actionPerformed(ActionEvent arg0) { // Le contrôleur communique avec l'IHM uniquement via le code retour. // Si true, le contrôleur a transmis la demande au modèle qui l'a traité avec succès. // false si le contrôleur n'a pas transmis la demande au modèle ou // si le modèle a rejeté la demande de modification. // Il est préférable en cas de refus que la notification vienne du contrôleur // sinon, c'est tous les utilisateurs qui seront notifiés de l'échec et pas uniquement // le demandeur. if (!ctrl.setNombre(bt.getText())) { System.out.println(bt.getText() + " est incorrect."); } } } }