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"
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.
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; } }
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(); } }
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(); } }
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.
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()
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
-
- 1. fwqsa Le 25/02/2021
-
- 2. fsaw Le 21/01/2021
-
- 3. fwas Le 22/12/2020
Ajouter un commentaire