TP8

NFP121 - TP8

NFP 121 - TP8

Pattern Décorateur






Question 1

Dans cette question les seules modifications à apporter sont dans les ActionListener => ActionPerformed.

Chaque choix fait par l'utilisateur décore la pizza avec des ingrédients puis est sauvegardé dans un élément "pizza"


Applet PizzaStore


package question1;

 


import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.text.DecimalFormat;

public class PizzaStore extends JApplet{
	
	public void init(){
		JRootPane rootPane = this.getRootPane();	
		rootPane.putClientProperty("defeatSystemEventQueueCheck", Boolean.TRUE);
		add(new IHMPizza());
	}



	private class IHMPizza extends JPanel{
    private JLabel         afficheur = new JLabel(
				" please, first choose your pizza, then the constituents but once clams...");
   
    private JButton        boutonSolo = new JButton("");
    private JButton        boutonClassic = new JButton("");
    private JButton        boutonCrust = new JButton("");
  
    private Checkbox       parmesan = new Checkbox("parmesan", null, true);
    private Checkbox       mozarella = new Checkbox("mozarella", null, false);
    private Checkbox       ham = new Checkbox("ham", null, false);
    private Checkbox       tomato = new Checkbox("tomato", null, false);
    private Checkbox       mushrooms = new Checkbox("mushrooms", null, false);
    private Checkbox       clams = new Checkbox("clams", null, false);

    private DecimalFormat  df = new DecimalFormat("##.##");  
    private JButton        boutonMake = new JButton("");
  
    private Pizza          pizza;
  
    
    public IHMPizza(){
      JPanel panelGlobal = new JPanel();
      JPanel panelBoutons = new JPanel();
      JPanel panelDecorations = new JPanel();
      JPanel panelMake = new JPanel();
      
  		panelGlobal.setLayout(new GridLayout(3,1));
  		afficheur.setEnabled(false);
      panelGlobal.add(afficheur);
      
      panelBoutons.setLayout(new FlowLayout(FlowLayout.CENTER));
      panelBoutons.add(boutonSolo);panelBoutons.add(boutonClassic);panelBoutons.add(boutonCrust);
      
      panelDecorations.setLayout(new GridLayout(1,6));
  		panelDecorations.add(parmesan);panelDecorations.add(mozarella);
  		panelDecorations.add(ham);panelDecorations.add(tomato);
  		panelDecorations.add(mushrooms);panelDecorations.add(clams);
  
      panelGlobal.add(panelBoutons);  
      panelGlobal.add(panelDecorations);  

  	  setLayout(new BorderLayout());  
      add(panelGlobal,"North");
      
      panelMake.setLayout(new FlowLayout(FlowLayout.CENTER));
      panelMake.add(boutonMake);
      add(panelMake,"Center");
      
     
      
  		boutonSolo.addActionListener(
  		  new ActionListener(){
  		    public void actionPerformed(ActionEvent ae){
  		      pizza = new PizzaSolo();
  		      validerLesDécorations();
  		    }
  		  });
  		
      boutonClassic.addActionListener(
      	new ActionListener(){
  		    public void actionPerformed(ActionEvent ae){
  		      pizza = new Classic();
  		      validerLesDécorations();
  		    }
  		  });
  		  
      boutonCrust.addActionListener(		  
        new ActionListener(){
  		    public void actionPerformed(ActionEvent ae){
  		      pizza = new GenerousCrust();
  		      validerLesDécorations();
  		    }
  		  });
      
  		  
      parmesan.addItemListener(new ItemListener(){
        public void itemStateChanged(ItemEvent ie){
          if(ie.getStateChange()==ItemEvent.SELECTED){
            pizza = new Parmesan(pizza);
          }
          afficherLaPizzaEtSonCoût();
      }}); 
      mozarella.addItemListener(new ItemListener(){
        public void itemStateChanged(ItemEvent ie){
          if(ie.getStateChange()==ItemEvent.SELECTED){
            pizza = new FreshMozarella(pizza);
          }
          afficherLaPizzaEtSonCoût();
      }});
      ham.addItemListener(new ItemListener(){
        public void itemStateChanged(ItemEvent ie){
          if(ie.getStateChange()==ItemEvent.SELECTED){
            pizza = new Ham(pizza);
          }
          afficherLaPizzaEtSonCoût();
      }}); 
      tomato.addItemListener(new ItemListener(){
        public void itemStateChanged(ItemEvent ie){
          if(ie.getStateChange()==ItemEvent.SELECTED){
            pizza = new Tomato(pizza);
          }
          afficherLaPizzaEtSonCoût();
      }});
      mushrooms.addItemListener(new ItemListener(){
        public void itemStateChanged(ItemEvent ie){
          if(ie.getStateChange()==ItemEvent.SELECTED){
            pizza = new Mushrooms(pizza);
          }
          afficherLaPizzaEtSonCoût();
      }}); 
      clams.addItemListener(new ItemListener(){
        public void itemStateChanged(ItemEvent ie){
          if(ie.getStateChange()==ItemEvent.SELECTED){
            pizza = new Clams(pizza);
          }
          else clams.setState(true);
          afficherLaPizzaEtSonCoût();
      }});
   
      
      boutonMake.addActionListener(
        new ActionListener(){
          public void actionPerformed(ActionEvent ae){
            invaliderLesDécorations();
            afficheur.setText("<html><FONT Color=red size=5>MAKING of the " + afficheur.getText() + "</html>");
          }
        });
        
      invaliderLesDécorations();
    }
    
    private void afficherLaPizzaEtSonCoût(){
      afficheur.setText("<html><FONT Color=blue size=4>"+ pizza.getDescription()
			+ "</FONT><FONT Color=red size=4> cost: " 
			+ df.format(pizza.cost()) + " €</Font></html>");
    }
    
    
    private void invaliderLesDécorations(){
      boutonMake.setEnabled(false);
		boutonMake.setText("<html><font size=3 color=green>compose your pizza ...</font></html>");
      boutonSolo.setEnabled(true);
		boutonSolo.setText("<html><font size=3 color=red>solo</font></html>");
      boutonClassic.setEnabled(true);
		boutonClassic.setText("<html><font size=3 color=red>classic</font></html>");
      boutonCrust.setEnabled(true);
		boutonCrust.setText("<html><font size=3 color=red>crust</font></html>");     
      parmesan.setState(false);
		mozarella.setState(false);ham.setState(false);
			tomato.setState(false);mushrooms.setState(false);clams.setState(false);
      parmesan.setEnabled(false);
		mozarella.setEnabled(false); ham.setEnabled(false);
			tomato.setEnabled(false);mushrooms.setEnabled(false);clams.setEnabled(false);
    }
    
    private void validerLesDécorations(){
      boutonMake.setEnabled(true);
		boutonMake.setText("<html><font size=3 color=red>make the pizza !</font></html>");
      boutonSolo.setEnabled(false);
		boutonSolo.setText("<html><font size=3 color=green>solo</font></html>");
      boutonClassic.setEnabled(false);
		boutonClassic.setText("<html><font size=3 color=green>classic</font></html>");
      boutonCrust.setEnabled(false);
		boutonCrust.setText("<html><font size=3 color=green>crust</font></html>");
      parmesan.setEnabled(true);
		mozarella.setEnabled(true);ham.setEnabled(true);
				tomato.setEnabled(true);mushrooms.setEnabled(true);clams.setEnabled(true);
      afficherLaPizzaEtSonCoût();
    }
    
  }
}



Question 2

La question 2.1 présente une architecture qui implémente déjà le pattern décorateur

Il faut ajouter la boisson Chocolate (qui est un objet de base qui peut être décoré).

Dans la question 2.2 on ajoute le condiment BeetSugar.

Chaque objet implémente la méthode cost(). Le décorateur utilise dans son constructeur et dans toutes les méthodes, l'appel super pendant son exécution.


Classe Chocolate


package question2;

/**
 * extrait de http://www.oreilly.com/catalog/hfdesignpat/
 */
public class Chocolate extends Beverage {
    /**
     * Constructeur donnant la description.
     */
  public Chocolate(){
      description = "Chocolate";
    }
    /**
     * Méthode cost.
     * @return le coût de la boisson : 2.10
     */
  public double cost() {
		return 2.10;
	}

}


Classe BeetSugar


package question2;

/**
 * extrait de http://www.oreilly.com/catalog/hfdesignpat/
 */
public class BeetSugar extends CondimentDecorator { 
    /**
     * Constructeur qui a besoin de Beverage pour être créé.
     * et défini avec super.
     */
    public BeetSugar(Beverage beverage) {
        super(beverage);
    }
    /**
     * Méthode getDescription.
     * @return la description de super avec l'actuel décorateur
     */
    public String getDescription() {
        return super.getDescription() + ", Beet Sugar";
    }
    /**
     * Méthode cost.
     * @return le coût de super avec le coût du condiment
     */
    public double cost() {
        return .10 + super.cost();
    }
}

Classe Beverage


package question2;
/**
 * extrait de http://www.oreilly.com/catalog/hfdesignpat/
 */
public abstract class Beverage {
	String description = "Unknown Beverage";
  
	public String getDescription() {
		return description;
	}
 
	public abstract double cost();
	
		public String toString(){
		  return this.getDescription() +" $"+ this.cost();
		}
	

}

Classe ChocolateTest


package question2;


public class ChocolateTest extends junit.framework.TestCase{
    private question2.Chocolate choco;
    private question2.Decaf decaf;



    public void setUp(){
        choco = new question2.Chocolate();
        decaf = new question2.Decaf();
    }

    
    
    public void testChocolate(){
        assertEquals(2.1, choco.cost(), 0.1);
    }

    public void testChocolateWhip(){
        question2.Beverage chocoSimpleWhip = new question2.Whip(choco);

        assertEquals(2.2, chocoSimpleWhip.cost(), 0.01);
    }
    
    public void testChocolateWhipWhip(){
        question2.Beverage chocoDoubleWhip = new question2.Whip(new question2.Whip(choco));

        assertEquals(2.3, chocoDoubleWhip.cost(), 0.01);
    }
    
    public void testChocolateWhipSoyMocha(){
        question2.Beverage chocoWhipSoyMocha = new question2.Mocha(new question2.Soy(new question2.Whip(choco)));

        assertEquals(2.55, chocoWhipSoyMocha.cost(), 0.01);
    }
    
    public void testDecafMilk(){
        question2.Beverage decafMilk = new question2.Milk(decaf);

        assertEquals(1.15, decafMilk.cost(), 0.01);
    }

    
    

    
}




Question 3

Avec l'unicité vérifiée à l'exécution, le constructeur du décorateur 'IrishWhisky' est le même avec un appel de super. Irish Whisky est un condiment qui peut être ajouté seulement une fois à beverage.


Classe IrishWhisky


package question3;
import question2.Beverage;
import question2.CondimentDecorator;
/**
 * Irish Whisky est un condiment qui peut être ajouté seulement une fois à beverage.
 */
public class IrishWhisky extends CondimentDecorator{

    public IrishWhisky(Beverage beverage) {
        super(beverage);
    }
    /**
     * getDescription().
     * @return la description de beverage.
     */
    public String getDescription() { 
        if(super.getDescription().contains("Irish Whisky")){
            return  super.getDescription();
        }else{
            return  super.getDescription() + ", Irish Whisky";
        }
    }
    /**
     * Methode cost().
     * @return le super coût.
     */
    public double cost() {
        if(super.getDescription().contains("Irish Whisky")){
            return  super.cost();
        }else{
            return super.cost() + 1.0;
        }
    }
}



Question 4

La classe UpperCaseInputStream est un des décorateurs possibles de FilterInputStream. Celle-ci transforme en Majuscule tous les caractères du fichier transmis en paramètre en redéfinissant les méthodes read()

Classe UpperCaseInputStream


package question4;

import java.io.InputStream;
import java.io.IOException;
import java.io.FilterInputStream;

/**
 * Cette classe "décore" un fichier (InputSream) par la conversion de tous
 * les caractères Minuscule en Majuscule
 * @author Oziol Joris
 * @version 31/12/2016
 */
public class UpperCaseInputStream  extends FilterInputStream{

    public UpperCaseInputStream(InputStream in){
        super(in);
    }

    /**
     * Redefinition de read() methode qui met en majuscule.
     * @return le caractère en majuscule
     */
    public int read() throws IOException{
        int c = super.read();
        if(c != -1){
            return Character.toUpperCase((char) c);
        } else {
            return c;
        }
    }
/**
 * Redefinition de read().
 * @return le caractère en maj avec PushBackInputStream
 */
    public int read(byte[] b, int off, int len) throws IOException{
        int c = super.read(b, off,len);
        for(int i = off; i<off+c; i++){
            b[i] = (byte)Character.toUpperCase((char)b[i]);

        }
        return c;
    }
}

Classe UpperCaseInputStreamTest


package question4;

import java.io.*;
import java.net.*;

public class UpperCaseInputStreamTest extends junit.framework.TestCase{

    public void testAccès_README_TXT(){
        try{
            InputStream is = new BufferedInputStream( new FileInputStream(new File("question4/README.TXT")));
            int c = is.read();
            assertTrue(" erreur de lecture ???", c!= -1);
            is.close();
        }catch(Exception e){
            fail(" Erreur sur ce fichier : README.TXT ??? " + e.getMessage());
        }
    }

    public void testUpperCase_README_TXT() throws Exception{
        InputStream is = new UpperCaseInputStream( new FileInputStream(new File("question4/README.TXT")));

        int c = is.read();
        while( c != -1){
            assertTrue("erreur !, '" + Character.valueOf((char)c) + "' ne semble pas être une majuscule ..."
					, Character.isUpperCase((char)c) || (char)c==' ');  
            c = is.read();
        }

        is.close();
    }

    public void testPushPackUpperCase_README_TXT() throws Exception{ 
        InputStream is = new UpperCaseInputStream(new FileInputStream(new File("question4/README.TXT")));
        int j = (int) new File("question4/README.TXT").length();
        byte[] b = new byte[(int)j];
        int off = 0;
        int len = j;

        int c = is.read(b, off, len);
         for(int i = off; i<off+c; i++){
            b[i] = (byte)Character.toUpperCase((char)b[i]);
            assertTrue("erreur !, '" + (byte)Character.toUpperCase((char)b[i])
			+"' ne semble pas être une majuscule ...",Character.isUpperCase((char)c) || (char)c==' ');
            c = is.read(b, off, len);
        }
        

        is.close();
    }
}




Conclusion, biliographie et remarques :

Ce Tp était plus agréable que son prédécesseur et plus facile à comprendre.

Commentaires

Ajouter un commentaire