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.");
}
}
}
}