MVC

Problème :

MVC

Le pattern Modele Vue Controle


Observer-Observable

Le pattern Observer-Observable est appliqué à la visualisation :


Le Modéle

Source de ModeleListeMots.java
import java.util.*;
/** modele de la liste de mots ordonnes sans doublon<br>
 *  est observable
 */
public class ModeleListeMots extends Observable 
{
  /** vecteur gerant la liste */
  private Vector vect;
  /** constructeur sans parametre */
  public ModeleListeMots() {
    vect = new Vector();
  }
  /** constructeur a partir d'un tableau de mots */
  public ModeleListeMots(String[]mots) {
    Arrays.sort(mots);
    int max = mots.length;
    vect = new Vector(max);
    for (int i=0; i<max; i++)
      vect.add(mots[i]);
  }
  /** ajoute un mot s'il n'existe pas */
  public void add(String mot) {
    if (!vect.contains(mot)) {
      int max = vect.size();
      int i=0;
      while ((i<max) && (mot.compareTo((String)vect.get(i)) >0))
        i++ ;
      vect.add(i, mot);
      this.setChanged();
      this.notifyObservers(this.toArray());
    }
  }
  /** fournit une copie tableau */ 
  public String[] toArray() {
    int max = vect.size();
    String[]result = new String[max] ;      
    for (int i=0; i<max; i++)
      result[i]=(String)vect.get(i);
    return result;
  }
  /** supprime un mot s'il existe */
  public void remove(String mot) {
    if (vect.remove(mot)) {
      this.setChanged();
      this.notifyObservers(this.toArray());
    }
  }
}

Le Controleur Console

Source de ControleurConsole.java
/** un controleur utilisant la console */
public class ControleurConsole 
{
  /** le modele a controler */
  private ModeleListeMots modele;
  /** constructeur */
  public ControleurConsole(ModeleListeMots modele) {
    this.modele = modele;
  } 
  /** la boucle de controle des commandes */
  public void run() {
    String rep;
    boolean encore;
    do {
      rep = Clavier.lireLigne().trim();
      encore = this.operer(rep);
    } while (encore);
  }
  /** analyse et traitement des commandes :<br>
   *  add mot ajoute un mot a la liste<br>
   *  del mot supprime un mot a la liste<br>
   *  q pour quitter
   */
  private boolean operer(String control) {
    boolean continuer = true;
    if (control == null)
      return continuer;
    else if (control.indexOf("del ") == 0) {
      String mot = control.substring(4,control.length()).trim();
      if (mot != null)
        this.modele.remove(mot);
    } else if (control.indexOf("add ") == 0) {
      String mot = control.substring(4,control.length()).trim();
      if (mot != null)
        this.modele.add(mot);
    } else  if (control.equals("q"))
      continuer = false;
    return continuer;
  }
}

Le controleur graphique swing

Source de ControleurGraphik.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/** un controleur swing */
public class ControleurGraphik extends JPanel implements ActionListener 
{
  /** le modele a controler */
  private ModeleListeMots modele;
  /** pour saisir un mot */
  private JTextField motField = null;
  /** constructeur */
  public ControleurGraphik(ModeleListeMots modele) {
    super(new BorderLayout());
    this.modele = modele;
    motField = new JTextField("");
    JButton addButton = new JButton("Add");
    addButton.addActionListener(this);
    JButton delButton = new JButton("Del");
    delButton.addActionListener(this);
    this.add(motField, BorderLayout.CENTER);
    this.add(addButton, BorderLayout.NORTH);
    this.add(delButton, BorderLayout.SOUTH);
  } 
  /** action des boutons add et del */
  public void actionPerformed(ActionEvent e){
    if (e.getActionCommand().equals("Add")) {
      this.modele.add(motField.getText().trim());
      motField.setText("");
    } else if (e.getActionCommand().equals("Del")) {
      this.modele.remove(motField.getText().trim());
      motField.setText("");
    }
  }
}

La vue en console

Source de VueConsole.java
import java.util.*;
/** vue de la liste par affichage sur l'ecran<br>
 *  observe le modele
 */
public class VueConsole implements Observer 
{
  /** le modele a afficher */
  private ModeleListeMots modele;
  /** constructeur */
  public VueConsole() {
    modele = null;
  }
  /** affecter un modele pour la vue console */
  public void setModele(ModeleListeMots modele) {
    this.modele = modele;
    modele.addObserver(this);
    this.miseAJour(modele.toArray());
  }
  /** mise a jour de la vue console */
  public void miseAJour(String[] listeMots) {
    if ((modele!= null) && (listeMots != null)) {
      System.out.println("----------");      
      int max = listeMots.length;
      for (int i=0; i<max; i++)
        System.out.println(listeMots[i]);      
      System.out.println("----------");  
    }
  }
  /** recoit une notification de changement du modele observe */
  public void update(Observable source, Object donnees) {	
    if ((source instanceof ModeleListeMots) && (donnees != null)
         && (donnees instanceof String[]))
      this.miseAJour((String[])donnees);
  }
} 

la vue graphique swing

Source de VueGraphik.java
import java.util.*;
import javax.swing.*;
/** vue de la liste par affichage swing<br>
 *  observe le modele
 */
public class VueGraphik extends JScrollPane implements Observer 
{
  /** le modele a afficher */
  private ModeleListeMots modele;
  /** le label d'affichage */
  private JLabel labelList = null;
  /** constructeur */
  public VueGraphik() {
	  super();
    modele = null;
    labelList = new JLabel("");
    this.setViewportView(labelList);
  }
  /** affecter un modele pour la vue  */
  public void setModele(ModeleListeMots modele) {
    this.modele = modele;
    modele.addObserver(this);
    this.miseAJour(modele.toArray());
  }
  /** mise a jour de la vue  */
  public void miseAJour(String[] listeMots) {
    if ((modele!= null) && (listeMots != null)) {
      StringBuffer lab = new StringBuffer("<html>");
      if (listeMots.length > 0) {
        int n = listeMots.length-1;
        for (int i=0; i<n; i++)
          lab.append(listeMots[i]+"<br>"); 
        lab.append(listeMots[n]); 
      }
      lab.append("</html>"); 
      // labelList.setText(lab.toString()); risque de deadlock
      final String texte = lab.toString();
      SwingUtilities.invokeLater(
        new Runnable() {
          public void run() {
            labelList.setText(texte); 
          }
        });   
    }
  }
  /** recoit une notification de changement du modele observe */
  public void update(Observable source, Object donnees) {	
    if ((source instanceof ModeleListeMots) && (donnees != null)
        && (donnees instanceof String[]))
      this.miseAJour((String[])donnees);
  }
} 

Le programme principal

Source de MVC.java
import javax.swing.*;
/** le MVC de gestion d'une liste de mots ordonnes */
public class MVC {
  public static void main(String[] args) {
    ModeleListeMots modele = new ModeleListeMots(args);
    ControleurConsole controlCon = new ControleurConsole(modele);
    ControleurGraphik controlGra = new ControleurGraphik(modele);
    VueConsole vueCon = new VueConsole();
    VueGraphik vueGra = new VueGraphik();
    JFrame frame = new JFrame("vue graphique");
    JPanel panel = new JPanel();
    panel.add(controlGra);
    JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                                           panel, vueGra);
    splitPane.setOneTouchExpandable(true);
    splitPane.setDividerLocation(0.5);
    frame.getContentPane().add(splitPane);
    frame.setSize(200,100);
    frame.setVisible(true);
    vueCon.setModele(modele);
    vueGra.setModele(modele);
    controlCon.run();
    frame.dispose();
  }
}

le Javadoc