JavaBean 1

Avantages et limites de la programmation Objet

Source de Prophete.java du package prophet_moins1
package prophet_moins1;
public class Prophete {
  private String nom = null;
  public String prophetie = null;

  public Prophete (String sonNom) {
    nom = sonNom;
    prophetie = "";
  }
  public String getNom () {
    return nom;
  }
  public String declame() {
    return prophetie;
  }
  public void proclame(String nouveauDelire) {
    prophetie = nouveauDelire;
  }
  public String toString () {
    return "prophete "+nom+" dit : "+prophetie;
  }
}
   

Source de Disciple.java du package prophet_moins1
package prophet_moins1;
public class Disciple {
  private String nom = "";
  public String pensee = "";
  private Prophete prophete = null;
  public Disciple (String sonNom, Prophete sonProphete) {
    nom = sonNom;
    prophete = sonProphete;
    pensee = prophete.prophetie ;
  }
  public String getNom() {
    return nom;
  } 
  public Prophete adore() {
    return prophete;
  }
  public void recoitLenseignement() {
    pensee = prophete.declame();
  }
  public String toString() {
    return "Disciple "+getNom()+" pense : "+pensee;
  }
}
 

Source de Sondage.java du package prophet_moins1
package prophet_moins1;
public class Sondage {
  public static void main (String args[]) {
    Prophete prophete = new Prophete("Brian");
    prophete.proclame("Peace and Love !");
    System.out.println(prophete.toString());
    Disciple disciple1 = new Disciple("Dupont", prophete);
    Disciple disciple2 = new Disciple("Durand", prophete);
    System.out.println(disciple1.toString());
    System.out.println(disciple2.toString());
    prophete.prophetie = "Alleluia !";
    System.out.println(prophete.toString());
    System.out.println(disciple1.toString());
    System.out.println(disciple2.toString());
    System.out.println("mise a jour de la pensee des disciples :");
    disciple1.pensee = prophete.prophetie;
    disciple2.recoitLenseignement();
    System.out.println(disciple1.toString());
    System.out.println(disciple2.toString());
  }
}
COMPILATION
$pwd
/home/ferment/java/phophet_moins1
$echo $CLASSPATH
.;..
$javac -d . Prophete.java
$javac -d . Disciple.java
$javac -d . Sondage.java
EXECUTION
$java phophet_moins1/Sondage
prophete Brian dit : Peace and Love !
Disciple Dupont pense : Peace and Love !
Disciple Durand pense : Peace and Love !
prophete Brian dit : Alleluia ! !
Disciple Dupont pense : Peace and Love !
Disciple Durand pense : Peace and Love !
mise a jour de la pensee des disciples :
Disciple Dupont pense : Alleluia !
Disciple Durand pense : Alleluia !
  • les lignes de la classe :
    • pas facile de deviner les noms de méthodes et en plus il y a plusieurs façons de faire
    • il faut forcer chaque disciple a acquérir la nouvelle prophétie pour en faire sa pensée unique !

propriétés simples et accesseurs

Source de Prophete.java du package prophet0
package prophet0;
public class Prophete {
  private String nom = null,
                 prophetie = null;

  public Prophete (String sonNom) {
    nom = sonNom;
    prophetie = "";
  }
  public String getNom () {
    return nom;
  }
  public String getProphetie () {
    return prophetie;
  }
  public void setProphetie (String nouveauDelire) {
    prophetie = nouveauDelire;
  }
  public String toString () {
    return "prophete "+nom+" dit : "+prophetie;
  }


 Source de Disciple.java du package prophet0
package prophet0;
public class Disciple {
  private String nom = "";
  private String pensee = "";
  private Prophete prophete = null;
  public Disciple (String sonNom, Prophete sonProphete) {
    nom = sonNom;
    prophete = sonProphete;
    pensee = prophete.getProphetie();
  }
  public String getNom() {
    return nom;
  }
  public String getPensee() {
    return pensee;
  }
  public Prophete getProphete() {
    return prophete;
  }

  public String toString() {
    return "Disciple "+getNom()+" pense : "+getPensee();
  }
  public void miseAJourPensee () {
    pensee = prophete.getProphetie();
  }
}

  
 Source de Sondage.java du package prophet0
package prophet0;
public class Sondage {
  public static void main (String args[]) {
    Prophete prophete = new Prophete("Brian");
    prophete.setProphetie("Peace and Love !");
    System.out.println(prophete.toString());
    Disciple disciple1 = new Disciple("Dupont", prophete);
    Disciple disciple2 = new Disciple("Durand", prophete);
    System.out.println(disciple1.toString());
    System.out.println(disciple2.toString());
    prophete.setProphetie("Alleluia !");
    System.out.println(prophete.toString());
    System.out.println(disciple1.toString());
    System.out.println(disciple2.toString());
    System.out.println("mise a jour de la pensee des disciples :");
    disciple1.miseAJourPensee();
    disciple2.miseAJourPensee();
    System.out.println(disciple1.toString());
    System.out.println(disciple2.toString());
  }
}

Evénement d'un bean

Nous voudrions que le prophète avertisse ses disciples de son changement de prophétie.

Source de Disciple.java du package prophet1
package prophet1;
public class Disciple
       implements ProphetieChangeListener {
  ....
  ....
  public void prophetieChanged (ProphetieChangedEvent evt) {
    pensee = evt.getProphetie();
  }
}
 
Source de ProphetieChangedEvent.java du package prophet1
package prophet1;
public class ProphetieChangedEvent extends java.util.EventObject
{
   protected String laProphetie;
   public ProphetieChangedEvent(Object source, String uneProphetie)
   {
      super(source);
      laProphetie = uneProphetie;
   }
   public String getProphetie()
   {
      return laProphetie;
   }
}
  
Source de ProphetieChangeListener.java du package prophet1
package prophet1;
public interface ProphetieChangeListener extends java.util.EventListener
{
   void prophetieChanged(ProphetieChangedEvent evt);
}

 
Source de Prophete.java du package prophet1
package prophet1;
import java.util.Vector;
public class Prophete {  
  private String nom = null;
  private String prophetie = null;
  private Vector prophetieChangeListeners = new Vector(); 
  .....
  .....
  public void setProphetie (String nouveauDelire) {
    if (! prophetie.equals(nouveauDelire)) {
      prophetie = nouveauDelire;
      this.notifyProphetieChange();
    }
  }
  public void addProphetieChangeListener(ProphetieChangeListener l)
  {
    if (!prophetieChangeListeners.contains(l))
      prophetieChangeListeners.addElement(l);
  }
  public void removeProphetieChangeListener(ProphetieChangeListener l)
  {
    if (prophetieChangeListeners.contains(l))
      prophetieChangeListeners.removeElement(l);
  }
  protected void notifyProphetieChange()
  {
    ProphetieChangedEvent evt = 
        new ProphetieChangedEvent(this, this.getProphetie());    
    for (int i = 0; i < prophetieChangeListeners.size(); i++)
    {
      ProphetieChangeListener client = 
         (ProphetieChangeListener)prophetieChangeListeners.elementAt(i);
      client.prophetieChanged(evt);
    }
  }
}
 
Source de Sondage.java du package prophet1
package prophet1;
public class Sondage {
  public static void main (String args[]) {
    Prophete prophete = new Prophete("Le Chat");
    prophete.setProphetie("Et pourquoi n'a-t-on jamais les pieds qui sentent les chaussettes ?");
    System.out.println(prophete.toString());
    Disciple disciple1 = new Disciple("Dupont");
    Disciple disciple2 = new Disciple("Durand");
    System.out.println(disciple1.toString());
    System.out.println(disciple2.toString());
    prophete.setProphetie("\nSi les lentilles vous font peter, portez des lunettes !");
    System.out.println(prophete.toString());
    System.out.println(disciple1.toString());
    System.out.println(disciple2.toString());
    System.out.println("\nConnectons les disciples sur le prophete:");
    prophete.addProphetieChangeListener(disciple1);
    prophete.addProphetieChangeListener(disciple2);
    prophete.setProphetie("la droite est un peu gauche, mais la gauche n'est pas tres adroite non plus !");
    System.out.println(prophete.toString());
    System.out.println(disciple1.toString());
    System.out.println(disciple2.toString());
  }
}
EXECUTION
$ java prophet1/Sondage       
prophete Le Chat dit : Et pourquoi n'a-t-on jamais les
   pieds qui sentent les chaussettes ?
Disciple Dupont pense : rien
Disciple Durand pense : rien
prophete Le Chat dit : 
Si les lentilles vous font peter, portez des lunettes !
Disciple Dupont pense : rien
Disciple Durand pense : rien
Connectons les disciples sur le prophete:
prophete Le Chat dit : la droite est un peu gauche,
  mais la gauche n'est pas tres adroite non plus !
Disciple Dupont pense : la droite est un peu gauche,
  mais la gauche n'est pas tres adroite non plus !
Disciple Durand pense : la droite est un peu gauche,
  mais la gauche n'est pas tres adroite non plus !
  • les lignes de la classe :
    • Désormais, un prophète notifie sa nouvelle prophétie par un message (ProphetieChangedEvent) à ses disciples : donc les disciples n'ont plus besoin d'interroger régulièrement leur prophète.
    • Pour ce faire, chaque disciple doit faire une cérémonie particulière pendant laquelle il indique à son prophète qu'il devient écouteur de ses messages prophétiques.
    • La mission d'un prophète devient plus lourde : il doit entretenir une liste des disciples à son écoute, et à chaque changement de prophétie, il doit envoyer un message à chacun des ses disciples. Dur, dur, la vie de prophète !

bean thread-safe

Remarquons que la gestion des listeners n'est pas thread-safe : des threads parallèles peuvent ajouter, enlever et essayer de notifier la liste des écouteurs sana exclusion mutuelle !

Source de Prophete.java du package prophet6
package prophet6;
import java.util.Vector;
public class Prophete {
   ...
   ...
   public synchronized void 
        addProphetieChangeListener(ProphetieChangeListener l) {
     if (!prophetieChangeListeners.contains(l))
       prophetieChangeListeners.addElement(l);
   }
   public synchronized void 
        removeProphetieChangeListener(ProphetieChangeListener l){
     if (prophetieChangeListeners.contains(l))
       prophetieChangeListeners.removeElement(l);
   }
   protected void notifyProphetieChange()
   {
     ProphetieChangedEvent evt = 
              new ProphetieChangedEvent(this, this.getProphetie());
     Vector listeCopie;
     synchronized(this) {
       listeCopie = (Vector) prophetieChangeListeners.clone();
     }
     // desormais un client de listeCopie peut se "remover" de la liste
     // officielle les listeners
     int nbre = listeCopie.size();
     for (int i = 0; i < nbre; i++) {
       ProphetieChangeListener client = 
                (ProphetieChangeListener)listeCopie.elementAt(i);
       client.prophetieChanged(evt);
     }
  }
}

Accès aux autres classes du package

Persistance

Source de Prophete.java du package prophet7
package prophet7;
import java.io.*;
...
public class Prophete 
       implements Serializable {
  ...
  ...
Source de Disciple.java du package prophet7
package prophet7;
import java.io.*;
public class Disciple
       implements ProphetieChangeListener, Serializable {
Source de Secte.java du package prophet7
import prophet7.*;
import java.io.*;
import java.util.*;
public class Secte implements Serializable {
  private Prophete prophete;
  private Vector lesDisciples;
  public static void main (String args[]) {
    Secte secte = null;
    File fichierSecte = new File("secte");
    if (! fichierSecte.exists())
      secte = new Secte();
    else
      secte = restauration(); 
    if (secte != null) {
      secte.sondage();
      secte.saisieNouvelleprophetie();
      secte.sondage();
      secte.sauvegarde();
   }
  }
  public Secte () {
    prophete = new Prophete("Le Chat");
    Disciple disciple1 = new Disciple("Dupont");
    Disciple disciple2 = new Disciple("Dujeune");
    prophete.addProphetieChangeListener(disciple1);
    prophete.addProphetieChangeListener(disciple2);
    prophete.setProphetie("La violence à la television\n"
          +"ca donne envie aux jeunes de tout casser\n"
          +"sauf, helas, la television");
    lesDisciples = new Vector();
    lesDisciples.add(disciple1);
    lesDisciples.add(disciple2);
  }
  public void sondage() {
    System.out.println(prophete.toString());
    for (int i=0; i<lesDisciples.size(); i++)
      System.out.println(lesDisciples.elementAt(i).toString()); 
  }   
  public void saisieNouvelleprophetie() {
    String encoreUne = null;
    do {
      System.out.println("quelle est la nouvelle prophetie ?");
      encoreUne = Clavier.lireLigne().trim();
    }
    while ((encoreUne == null) &&  encoreUne.equals(""));
    prophete.setProphetie(encoreUne); 
  }   
  private void sauvegarde () {
    try {
         ObjectOutputStream flotEcriture = 
             new ObjectOutputStream(
                new FileOutputStream(new File("secte")));
         flotEcriture.writeObject(this);
         flotEcriture.close();
         System.out.println("sauvegarde dans le fichier secte");
       } catch (IOException e) {
         System.out.println(" erreur :" + e.toString());
       } 
  } 
  private static Secte restauration () {
     try {
       ObjectInputStream flotLecture = 
             new ObjectInputStream(
                new FileInputStream(new File("secte")));
       Object lu = flotLecture.readObject();
       if (lu instanceof Secte) 
         return (Secte)lu;
       else {
         System.out.println("pas une secte");
         return null ;
        } 
       } catch (Exception e) {
         System.out.println(" erreur :" + e.toString());
         return null ;
       } 
  }
}
Accès aux autres classes du package

EXECUTION
$java  Secte
prophete Le Chat dit : La violence ?? la television
ca donne envie aux jeunes de tout casser
sauf, helas, la television
Disciple Dupont pense : La violence ?? la television
ca donne envie aux jeunes de tout casser
sauf, helas, la television
Disciple Dujeune pense : La violence ?? la television
ca donne envie aux jeunes de tout casser
sauf, helas, la television
quelle est la nouvelle prophetie ?
sea, sex and sun ... c'est fini ! maintenant on dit : 
 mazout, sida et melanome
prophete Le Chat dit : sea, sex and sun ... c'est fini ! 
    maintenant on dit : mazout, sida et melanome
Disciple Dupont pense : sea, sex and sun ... c'est fini ! 
    maintenant on dit : mazout, sida et melanome
Disciple Dujeune pense : sea, sex and sun ... c'est fini ! 
    maintenant on dit : mazout, sida et melanome
sauvegarde dans le fichier secte

$ java  Secte
prophete Le Chat dit : sea, sex and sun ... c'est fini ! 
    maintenant on dit : mazout, sida et melanome
Disciple Dupont pense : sea, sex and sun ... c'est fini ! 
    maintenant on dit : mazout, sida et melanome
Disciple Dujeune pense : sea, sex and sun ... c'est fini ! 
    maintenant on dit : mazout, sida et melanome
quelle est la nouvelle prophetie ?
.........
  • les lignes de la classe :
    • Nous voulons gérer sur une longue période une secte comprenant un prophète et ses disciples : il faudra sauvegarder la secte entre 2 exécutions.
    • C'est donc une secte persistente !
    • Il est facile de sérialiser les disciples.
    • Par contre, sérialiser le prophète pose le problème de conserver ses "écouteurs".
    • Si ce n'était pas fait, il faudrait que les disciples soient re-enregistrés auprès du prophète. Les récepteurs d'événements sont donc sérialisés.

sérialisation en XML


Source de Prophete.java du package prophet9
package prophet9;
public class Prophete {
  private String nom = null;
  private String prophetie = null;
  public Prophete () {
    nom = "";
    prophetie = "";
  }
  ....
  public void setNom (String sonNom) {
    nom = sonNom;
  }
  ...
  • Pattern de construction des beans :
    • un bean doit avoir obligatoirement et au moins un constructeur par defaut : cad sans paramètre
    • c'est nécessaire aux IDEs pour manipuler les beans

Source de SerialXML.java du package prophet9
package prophet9;
import java.beans.*; 
import java.io.*; 
public class SerialXML {    
  public static void main(String[] args) { 
    try {
      XMLEncoder e = new XMLEncoder(new BufferedOutputStream
                           (new FileOutputStream("prophet.xml")));        
      Prophete p = new Prophete("Le Chat");
      p.setProphetie("I'm bo");
      e.writeObject(p); 
      e.close(); 
    } catch (Throwable t) { 
      System.out.println("erreur encodage"); 
      t.printStackTrace(); 
      System.exit(1);
    } 
    System.out.println("encodage termine");      
    try {
      XMLDecoder d = new XMLDecoder(new BufferedInputStream
                           (new FileInputStream("prophet.xml")));      
      Object o = d.readObject(); 
      d.close(); 
      System.out.println(o); 
    } catch (Throwable t) { 
      System.out.println("erreur decodage");
      t.printStackTrace(); 
    }      
  }    
}
EXECUTION
$java prophet9.SerialXML
encodage termine
prophete Le Chat dit : I'm bo
$ cat prophet.xml
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.4.2-02" class="java.beans.XMLDecoder">
 <object class="prophet9.Prophete">
  <void property="nom">
   <string>Le Chat</string>
  </void>
  <void property="prophetie">
   <string>I&apos;m bo</string>
  </void>
 </object>
</java>
  • les lignes de la classe :
    • Depuis la version Java 1.4, les beans disposent d'une sérialisation en document XML :
      • XMLEncoder
      • XMLDecoder
    • il n'est pas nécessaire d'implémenter l'interface Serializable
    • Par contre, il est obligatoire de disposer d'un constructeur par défaut, sinon de décodeur ne peut instancier le bean.
    • Efficace mais plus dur à "customiser"
  

Source de SerialXMLFrame.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.beans.*;
public class SerialXMLFrame  {
  public static void main(String[] args) {
    try {
        JFrame frame = new JFrame(); 
        frame.setTitle("le titre");
        Container c = frame.getContentPane(); 
        JLabel label = new JLabel("un label");
        c.add(label);
        JButton bouton = new JButton("un bouton");
        c.add(bouton);
      XMLEncoder e = new XMLEncoder(
        new BufferedOutputStream(
          new FileOutputStream("sauve.xml")));
      e.writeObject(frame);
      e.close();
    } catch (IOException e) {
      System.out.println(e);
    }
  }
}
EXECUTION
$ java serialXMLFrame
$ cat sauve.xml
<?xml version="1.0" encoding="UTF-8"?> 
<java version="1.4.2-02" class="java.beans.XMLDecoder"> 
 <object class="javax.swing.JFrame"> 
  <void property="contentPane"> 
   <void method="add"> 
    <object class="javax.swing.JLabel"> 
     <void property="text"> 
      <string>un label</string> 
     </void> 
    </object> 
   </void> 
   <void method="add"> 
    <object class="javax.swing.JButton"> 
     <string>un bouton</string> 
    </object> 
   </void> 
  </void> 
  <void property="name"> 
   <string>frame0</string> 
  </void> 
  <void property="title"> 
   <string>le titre</string> 
  </void> 
 </object> 
</java>
  • les lignes de la classe :
    • cela fonctionne très bien sur les les beans AWT et SWING

exercices