TP_Commit

NFP 121 - TP_Commit

Les Transactions

  Tp commitTp commit
 

Question 1.1 :

Voici une implémentation de la classe Contributeur

 

La classe Contributeur:

 
package question1; 

/**  
 * Le contributeur est le "leaf" de notre pattern composite héritant du composant Cotisant  
 * et composant le GroupeDeContributeur.  
 * @author Morane Otilia  
 * @version 10.12.2014  */ 
public class Contributeur extends Cotisant{
    private int solde; 
    /**      
     * Constructeur d'un Contributeur avec param      
     * @param nom contributeur      
     * @praram somme de départ (non négative)      */ 
    public Contributeur(String nom, int somme){ 
        super(nom); 
        if(somme>=0){                             
            this.solde = somme; 
        } else { throw new RuntimeException("nombre négatif !!!"); } 
    } 

    /**      
     * retourne le solde du compte      
     * @return solde du compte      
     */ 
    public int solde(){ 
        return this.solde; 
    } 

    public int nombreDeCotisants(){ 
        return 1; 
    } 

    /**      
     * debiter du compte la somme entrée seulement si positive et seulement si celle-ci est inférieure au      *  @throws RuntimeException new RuntimeException("nombre négatif !!!")      
     *   @throws SoldeDebiteurException      
     *   @param somme à débiter      */ 
    public void debit(int somme) throws SoldeDebiteurException{
        if(somme > solde){ 
            throw new SoldeDebiteurException(); 
        } else if (somme < 0){ 
            throw new RuntimeException("nombre négatif !!!"); 
        }else{                             
            this.solde -= somme; 
        } 
    } 

    /**      
     * créditer le compte de la somme entrée seulement si celle-ci est positive ou nulle      
     * throws RuntimeException new RuntimeException("nombre négatif !!!");      
     * @param somme à créditer      */
    public void credit(int somme){ 
        if(somme <  0){ 
            throw new RuntimeException("nombre négatif !!!"); 
        } else{                             
            this.solde += somme; 
        } 
    } 

    /**      
     * affecter un nouveaux solde au compte      
     * throws RuntimeException new RuntimeException("nombre négatif !!!");      
     */ 
    public void affecterSolde(int somme){
        if(somme <0) 
            throw new RuntimeException("nombre négatif !!!"); 
        try{                             
            debit(solde());                             
            credit(somme);// mode élégant ... 
        }catch(SoldeDebiteurException sde){ // exception peu probable             
            this.solde = somme; // mode efficace ... 
        } 
    } 

    /**      
     * La méthode de visite d'un visiteur de type T      
     */ 
    public <T> T accepter(Visiteur<T> visiteur){ 
        return visiteur.visite(this); 
    } 

    /**      
     * Transformation d'un contributeur en String d'un arbre XML      
     */ 
    public String toString(){
        return "<Contributeur : " + nom + "," + solde + ">"; 
    } 
} 
 

Question 1.2 :

Implémentation complète de la classe GroupeDeContributeur

Pour réussir cette implémentation j'ai utilisé une boucle foreach : pour chaque cotisant de la liste ...

 

La classe GroupeDeContributeur :

 
package question1;

import java.util.Iterator;
import java.util.NoSuchElementException;

import java.util.List;
import java.util.ArrayList;
import java.util.Stack;

public class GroupeDeContributeurs extends Cotisant implements Iterable<Cotisant>{
    private List<Cotisant> liste;

    /**      
     * Constructeur d'un groupe de contributeurs      
     * @param nom du groupe      
     */ 
    public GroupeDeContributeurs(String nomDuGroupe){ 
        super(nomDuGroupe);                             
        this.liste = new ArrayList<Cotisant>(); 
    } 
    
    /**      
     * méthode d'ajout d'un cotisant au groupe des contributeurs qui      
     * devient le parent de ce cotisant.      
     * @param cotisant-contributeur      
     */ 
    public void ajouter(Cotisant cotisant){                             
        this.liste.add(cotisant);                             
        cotisant.setParent(this); 
    } 
    
    /**      
     * méthode récursive dans le cas d'un groupe de contributeurs interne      
     *@return  Le nombre de cotisants      
     */ 
    public int nombreDeCotisants(){ 
        int nombre = 0;                             
        Iterator<Cotisant> it = liste.iterator();
        while(it.hasNext()){                             
            Cotisant c = it.next(); 
            if(c instanceof Contributeur){                             
                nombre +=1; }
            else{                             
                nombre += c.nombreDeCotisants(); 
            } 
        } 
        return nombre; 
    } 
     
    /**      
     * @return la chaîne de caractère qui représente ce groupe      
     */ 
    public String toString(){                             
        String str = new String(); 
        for(Cotisant c: this.liste){                             
            str +=  c.toString()+" \n " ; 
        } 
        return str; 
    } 
      
    /**      
     * @return la liste des Cotisants      
     */ 
    public List<Cotisant> getChildren(){ 
        return this.liste; 
    } 
    
    /**      
     * débiter la somme de tous les comptes du groupe      
     * @param int somme      
     */ 
    public void debit(int somme) throws SoldeDebiteurException{
        if(somme <  0){ 
            throw new RuntimeException("nombre négatif !!!"); 
        } 
        else{
            for(Cotisant c: this.liste){
                try{                             
                    c.debit(somme); 
                }catch( SoldeDebiteurException e){ 
                    throw new SoldeDebiteurException(); 
                } 
            } 
        } 
    } 
    
    /**      
     * créditer la somme en param de tous les cotisant du groupe  
	 * @param int somme 
     */ 
    public void credit(int somme){ 
        if(somme <  0){ 
            throw new RuntimeException("nombre négatif !!!"); 
        } 
        else{ 
            for(Cotisant c: this.liste){                             
                c.credit(somme); 
            } 
        } 
    } 
    
    /**      
     * @return le solde total     
     */
    public int solde(){ 
        int solde = 0; 
        for(Cotisant c: this.liste){                            
            solde += c.solde(); 
        } 
        return solde; 
    } 
    // méthodes fournies

    public Iterator<Cotisant> iterator(){
        return new GroupeIterator(liste.iterator());
    }

    private class GroupeIterator implements Iterator<Cotisant>{
        private Stack<Iterator<Cotisant>> stk;

        public GroupeIterator(Iterator<Cotisant> iterator){
            this.stk = new Stack<Iterator<Cotisant>>();
            this.stk.push(iterator);
        }

        public boolean hasNext(){
            if(stk.empty()){
                return false;
            }else{
                Iterator<Cotisant> iterator = stk.peek();
                if( !iterator.hasNext()){
                    stk.pop();
                    return hasNext();
                }else{
                    return true;
                }
            }
        }

        public Cotisant next(){
            if(hasNext()){
                Iterator<Cotisant> iterator = stk.peek();
                Cotisant cpt = iterator.next();
                if(cpt instanceof GroupeDeContributeurs){
                    GroupeDeContributeurs gr = (GroupeDeContributeurs)cpt;
                    stk.push(gr.liste.iterator());
                }
                return cpt;
            }else{
                throw new NoSuchElementException();
            }
        }

        public void remove(){
            throw new UnsupportedOperationException();
        }
    }

    public <T> T accepter(Visiteur<T> visiteur){
        return visiteur.visite(this);
    }

}
 

Question 2.1 :

Le patron Visiteur

une implémentation complète de la classe CompositeValide.

Le solde de chaque contributeur doit être supérieur ou égal à 0 et il n’existe pas de groupe n’ayant pas de contributeurs.

 

La classe SansDoublon vérifie que les noms des groupes et des contributeurs sont différents.

 

On aura une méthode booléenne de la visite des contributeurs et une autre méthode booléenne pour la visite des GroupeDeContributeurs

 

CompositeValide

 
package question2;

import question1.Contributeur;
import question1.GroupeDeContributeurs;
import question1.Visiteur;
import question1.Cotisant;


/**  
 * Un visiteur qui détermine la validité du Composite  
 * Le solde de chaque contributeur doit être supérieur ou égal à 0  
 * et il n’existe pas de groupe n’ayant pas de contributeurs.  
 */ 
public class CompositeValide implements Visiteur<Boolean>{ 
    /**    
     * @return vrai si solde >=    
     */ 
    public Boolean visite(Contributeur c){ 
        return c.solde()>= 0; 
    } 

    /**    
     * Appel de la visite de l'élément atomique    
     * @return vrai si il existe au moins un élément Contributeur    
     */ 
    public Boolean visite(GroupeDeContributeurs g){ 
        if(g.nombreDeCotisants()<=0){ 
            return false; 
        } 
        for(Cotisant c : g.getChildren()){ 
            if( !c.accepter(this)){ 
                return false; 
            } 
        } return true ; 
    } 
}
 

SansDoublon

 
package question2;

import question1.*;
import java.util.Set;
import java.util.TreeSet;

public class SansDoublon implements Visiteur<Boolean>{
  public Boolean visite(Contributeur c){
    return false; // a compléter;
  }
  
  public Boolean visite(GroupeDeContributeurs g){
    boolean res = false;// a compléter
    // a compléter
    return res ;
  }
  
}
 

Question 2.2 :

La Classe Débit Maximal

 

DebitMaximal

 
package question2;

import question1.Contributeur;
import question1.GroupeDeContributeurs;
import question1.Visiteur;
import question1.Cotisant;


/**  
 * Un visiteur qui retourne le débit maximal d'un Contributeur ou d'un GroupeDeContributeurs  
 */ 
public class DebitMaximal implements Visiteur<Integer>{ 
    /**      
     * @return le débit maximal d'un seule contributeur      
     */
    public Integer visite(Contributeur c){ 
        return c.solde(); 
    } 

    /**      
     * appel de la visite d'un élément Contributeur      
     * @return le solde minimale de tous les Contributeurs      
     */ 
    public Integer visite(GroupeDeContributeurs g){ 
        int res = 0; 
        for(Cotisant c : g.getChildren()){ 
            int temp = c.accepter(this);
            if (res==0 || temp < res ){                             
                res =temp; 
            } 
        } 
        return res ;

    } 
} 
 

Question 3 :

Cette question est assez difficile. Il fallait comprendre que l'originator était la transaction elle-même. Il fallait ensuite créer le gardien (caretaker) et le memento (sauvegarde restitution)

Memento fait appel aux visiteurs de sauvegarde et de restitution pour effectuer les visites sur les éléments du Contributeur et les composites GroupeDeContributeurs.

j'ai utilisé une hashmap de Cotisant avec l'ancien solde associé à ce Cotisant

 

Pour le patron Template Method : il ya seulement une transaction concrète, TransactionDebit. Elle fait appel à TransactionSauvegarde car le débit est appelé dans la classe abstraite AbstractTransaction.

 

Memento

 
package question3;

import question1.*;
import java.util.*;

public class Memento {
    // Note : Un usage du patron Memento, 
    //        d’un premier visiteur pour la sauvegarde et 
    //        d’un second pour la restitution du composite, 
    //        représentent une solution possible. 

    private HashMap<Cotisant,Integer> state; 

    public Memento(Cotisant c) {                             
        this.state = c.accepter(new VisiteurSauvegarde()); 
    } 

    public void setState(Cotisant c) { 
        // restitution         
        c.accepter(new VisiteurRestitution(this.state)); 
    } 

}
 

Gardien

 
package question3;
import java.util.Stack;

public class Gardien{
    private Stack<Memento> mementoStk;
    
    public Gardien(){
      this.mementoStk = new Stack<Memento>();
    }
    public Memento getMemento() {
        return this.mementoStk.pop();
    }
    
    public void setMemento(Memento memento){
        this.mementoStk.push(memento);
    }
  }
 

TransactionDebit

 
package question3;

import question1.*;


public class TransactionDebit extends AbstractTransaction{ 
    private Gardien gardien; 
    
    public TransactionDebit(Cotisant cotisant){ 
        super(cotisant);                             
        this.gardien = new Gardien(); 
    } 

    /**      
     * avant une transaction l'état initiale est sauvegardé      
     */ 
    public void beginTransaction(){                             
        gardien.setMemento(new Memento(cotisant)); 
    } 

    /**      
     * à la fin d'une transaction      
     */ 
    public void endTransaction(){ } 

    /**      
     * si une erreur est levée, retour à l'état précédent      
     */
    public void rollbackTransaction(){                             
        gardien.getMemento().setState(cotisant); 
    } 
} 
 

VisiteurRestitution

 
package question3;
import java.util.HashMap;
import question1.*;

public class VisiteurRestitution implements question1.Visiteur<Cotisant> { 
    private HashMap<Cotisant, Integer> state; 
    
    public VisiteurRestitution(HashMap<Cotisant, Integer> state){                             
        this.state=state; 
    } 
    
    public Cotisant visite(Contributeur c){ 
        int somme = this.state.get(c);                            
        c.affecterSolde(somme); 
        return c ; 
    } 

    public Cotisant visite(GroupeDeContributeurs g){ 
        for(Cotisant c : g.getChildren()){
            c.accepter(this); 
        } 
        return g; 
    } 
} 
 

VisiteurSauvegarde

 
package question3;
import java.util.HashMap;
import question1.*;
/**  
 * Visiteur qui implémente le clone visiteur du cours pour pouvoir ne pas sauvegarder le pointeur dans  
 * le Memento  
 */ 
public class VisiteurSauvegarde implements question1.Visiteur<HashMap<Cotisant, Integer>>{
    public HashMap<Cotisant, Integer> visite(Contributeur c){ 
        //Contributeur clone = new Contributeur(c.nom(),c.solde());         
        HashMap<Cotisant, Integer> toSave = new HashMap<Cotisant, Integer>();                             
        Integer solde = new Integer(c.solde());                             
        toSave.put(c, solde); return toSave; 
    } 

    public HashMap<Cotisant, Integer> visite(GroupeDeContributeurs g) {                            
        HashMap<Cotisant, Integer> toSave = new HashMap<Cotisant, Integer>(); 
        for(Cotisant c: g.getChildren()){                             
            HashMap<Cotisant, Integer> nouveaux = c.accepter(this);                             
            toSave.putAll(nouveaux); 
        } 
        return toSave; 
    } 
}
 

Question 4 :

Ajout d'une méthode crédit dans la classe AbstractTransaction qui utilise la sauvegarde de la classe concrète TransactionDebit.

 

IHM

 
package question4;

import question1.Contributeur;
import question1.GroupeDeContributeurs;
import question2.*;
import question3.*;
import static question2.Main.*;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import org.jdom.*;
import org.jdom.output.*;
import java.io.ByteArrayOutputStream;

public class IHM extends JFrame {

    private JTextArea resultat = new JTextArea("", 7,60);
    private JButton debiter = new JButton("débiter");
    private JButton crediter = new JButton("créditer");
    private JTextField somme = new JTextField(4);

    private GroupeDeContributeurs g;

    public IHM() {
        this.setTitle("Cotisant");
        Container container = this.getContentPane();
        somme.setText("40");
        container.setLayout(new BorderLayout());

        container.add(resultat, BorderLayout.NORTH);
        JPanel p = new JPanel(new FlowLayout());
        p.add(somme);
        p.add(debiter);
        p.add(crediter);
        container.add(p, BorderLayout.SOUTH);

        g = new GroupeDeContributeurs("g");
        g.ajouter(new Contributeur("g_a",100));
        g.ajouter(new Contributeur("g_b",50));
        g.ajouter(new Contributeur("g_c",150));
        GroupeDeContributeurs g1 = new GroupeDeContributeurs("g1");
        g1.ajouter(new Contributeur("g1_a1",70));
        g1.ajouter(new Contributeur("g1_b1",200));
        g.ajouter(g1);

        try{
            resultat.setText(Main.arbreXML(g)); //actualiser();
        }catch(Exception e){}

        debiter.addActionListener(new ActionListener(){ 
                public void actionPerformed(ActionEvent ae){                             
                    AbstractTransaction transaction = new TransactionDebit(g); 
                    try{                             
                        transaction.debit(Integer.parseInt(somme.getText())); 
                    }catch(Exception e){} 
                    try{                             
                        resultat.setText(Main.arbreXML(g)); 
                        //actualiser(); 
                    }catch(Exception e){} 
                } 
            }
        );
        crediter.addActionListener(new ActionListener(){ 
                public void actionPerformed(ActionEvent ae){                             
                    AbstractTransaction transaction = new TransactionDebit(g);                            
                    transaction.credit(Integer.parseInt(somme.getText())); 
                    try{                             
                        resultat.setText(Main.arbreXML(g)); 
                        //actualiser(); 
                    }catch(Exception e){} 
                } 
            }
        );   

        this.pack();
        this.setVisible(true);
    }

    public static void main() {
        new IHM();    
    }    

}
 

Conclusion, biliographie et remarques :

TP intéressant, on a vu de nouveau une autre utilisation du pattern visiteur ainsi que l'utilisation de memento et du patron template method. Bref un peu de tout qui s'entremèle avec symbiose.

Commentaires

Ajouter un commentaire

 
×