Design pattern MVC - est ce que je suis dans le bon ?
Bonjour,
J'ai repris un tuto sur openclassroom où on fait une calculatrice en utilisant le design pattern MVC. J'ai complètement refait sans utiliser interfaces Observer et observable qui sont obsolètes. J'aimerai avoir des critiques de votre part, en particulier sur ce design pattern (mais tous autres critiques seront les bienvenus).
Merci d'avance.
Pièce jointe 591528
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| package apj.p3.calculatrice;
import javax.swing.JFrame;
public class App {
public static void main(String[] args) {
JFrame f = new Gui(new CalcModel());
f.setVisible(true);
}
} |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
package apj.p3.calculatrice;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Gui extends JFrame {
private static final long serialVersionUID = 1L;
String[] operateur = { "+", "-", "/", "*" };
/* On associe un model abstrait */
AbstractModel calcModel;
/* On associe un controller abstrait */
AbstractController controller;
JLabel label;
public Gui(AbstractModel caclModel) {
super("Calculatrice v2");
this.calcModel = new CalcModel();
this.controller = new CalcController(this.calcModel);
/* -- Construction de la JFRAME -- */
this.setSize(270, 270);
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
this.setResizable(false);
this.setLocationRelativeTo(null);
/* -- Construction des composants -- */
JPanel pan = (JPanel) this.getContentPane();
pan.setLayout(new BorderLayout());
pan.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
this.label = createLabel();
pan.add(this.label, BorderLayout.NORTH);
pan.add(createPanChiffre(), BorderLayout.CENTER);
pan.add(createPanOp(), BorderLayout.EAST);
}
/**
*
* @return le JPanel où se trouve les boutons des opérations et clear
*/
private JPanel createPanOp() {
JPanel panOp = new JPanel();
panOp.setLayout(new GridLayout(5, 1, 5, 5));
panOp.add(createBtnClear());
for (String string : operateur) {
panOp.add(createBtnOp(string));
}
return panOp;
}
/**
*
* @return le JPanel où se trouve les chiffres, le point et le bouton égal
*/
private JPanel createPanChiffre() {
JPanel panChiffre = new JPanel();
panChiffre.setLayout(new GridLayout(4, 3, 5, 5));
for (int i = 1; i < 10; i++) {
panChiffre.add(this.createBtnChiffre(i));
}
panChiffre.add(this.createBtnChiffre("0"));
panChiffre.add(this.createBtnChiffre("."));
panChiffre.add(this.createBtnEgal());
return panChiffre;
}
/**
*
* @return le JLabel d'affichage des resultats
*/
private JLabel createLabel() {
JLabel label = new JLabel();
label.setBorder(BorderFactory.createLineBorder(Color.black));
label.setText("0");
calcModel.addPropertyChangeListener((e) -> label.setText(e.getNewValue().toString()));
return label;
}
private JButton createBtnChiffre(String chiffre) {
JButton btn = new JButton(chiffre);
btn.addActionListener(this::actionChiffre);
return btn;
}
private JButton createBtnChiffre(int chiffre) {
return createBtnChiffre(Integer.toString(chiffre));
}
private JButton createBtnEgal() {
JButton btn = new JButton("=");
btn.addActionListener(this::actionEgal);
return btn;
}
private JButton createBtnOp(String op) {
JButton btn = new JButton(op);
btn.addActionListener(this::actionOperateur);
return btn;
}
private JButton createBtnClear() {
JButton btn = new JButton("C");
btn.addActionListener(this::actionClear);
return btn;
}
private void actionChiffre(ActionEvent e) {
try {
this.label.setText(controller.controleChiffre(((JButton) e.getSource()).getText()));
} catch (IllegalArgumentException e1) {
this.actionClear(e);
this.label.setText(e1.getMessage());
}
}
private void actionEgal(ActionEvent e) {
try {
controller.controleEgal();
} catch (IllegalArgumentException e1) {
this.actionClear(e);
this.label.setText(e1.getMessage());
}
}
private void actionOperateur(ActionEvent e) {
String txtBtn = ((JButton) e.getSource()).getText();
try {
controller.controleOp(txtBtn);
} catch (IllegalArgumentException e1) {
this.actionClear(e);
this.label.setText(e1.getMessage());
}
}
private void actionClear(ActionEvent e) {
controller.controleCancel();
}
} |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
|
package apj.p3.calculatrice;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
public abstract class AbstractModel {
float rslt;
PropertyChangeSupport support;
AbstractModel() {
support = new PropertyChangeSupport(this);
}
public abstract boolean operationAdditionner (float nbr);
public abstract boolean operationSoustraire (float nbr);
public abstract boolean operationDiviser (float nbr);
public abstract boolean operationMultiplier (float nbr);
public abstract boolean reset ();
protected float getRslt() {
return rslt;
}
protected void setRslt(float rslt) {
support.firePropertyChange("resultat", this.rslt , rslt);
this.rslt = rslt;
}
protected PropertyChangeSupport getSupport() {
return support;
}
protected void setSupport(PropertyChangeSupport support) {
this.support = support;
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
this.support.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
this.support.removePropertyChangeListener(listener);
}
} |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
|
package apj.p3.calculatrice;
import java.util.regex.Pattern;
public abstract class AbstractController {
String rgx;
Pattern pattern;
String chiffre;
String op;
String opPre = null;
AbstractModel model;
boolean nouveauChiffre;
boolean negatif;
AbstractController() {
this.setRgx(".*");
this.pattern = Pattern.compile(rgx);
this.setChiffre(null);
this.setOp(null);
this.setOpPre(null);
this.setModel(null);
this.setNouveauChiffre(true);
this.setNegatif(false);
}
/**
* Controle le chiffre est correcte
* @param chiffre correspond au bouton appuyé
* @return le nombre complèt à afficher
*/
public abstract String controleChiffre(String chiffre);
public abstract void controleOp(String operateur);
public abstract void controleCancel();
public abstract void controleEgal();
protected String getChiffre() {
return chiffre;
}
protected void setChiffre(String chiffre) {
if (chiffre != null) {
if (pattern.matcher(chiffre).matches())
this.chiffre = chiffre;
else
throw new IllegalArgumentException("Erreur : chiffre incorrect");
}
}
protected String getOp() {
return op;
}
protected void setOp(String op) {
this.op = op;
}
protected AbstractModel getModel() {
return model;
}
protected void setModel(AbstractModel model) {
this.model = model;
}
protected String getOpPre() {
return opPre;
}
protected void setOpPre(String opPre) {
this.opPre = opPre;
}
protected boolean isNouveauChiffre() {
return nouveauChiffre;
}
protected void setNouveauChiffre(boolean nouveauChiffre) {
if(nouveauChiffre)
this.setNegatif(false);
this.nouveauChiffre = nouveauChiffre;
}
public String getRgx() {
return rgx;
}
public void setRgx(String rgx) {
this.rgx = rgx;
}
public boolean isNegatif() {
return negatif;
}
public void setNegatif(boolean negatif) {
this.negatif = negatif;
}
} |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
|
package apj.p3.calculatrice;
public class CalcModel extends AbstractModel{
@Override
public boolean reset() {
this.setRslt(0);
return false;
}
@Override
public boolean operationAdditionner(float nbr) {
this.setRslt(this.getRslt() + nbr);
return false;
}
@Override
public boolean operationSoustraire(float nbr) {
this.setRslt(this.getRslt() - nbr);
return false;
}
@Override
public boolean operationDiviser(float nbr) {
this.setRslt(this.getRslt() / nbr);
return false;
}
@Override
public boolean operationMultiplier(float nbr) {
this.setRslt(this.getRslt() * nbr);
return false;
}
} |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
|
package apj.p3.calculatrice;
import java.util.regex.Pattern;
public class CalcController extends AbstractController {
public CalcController(AbstractModel model) {
this.setModel(model);
this.setRgx("^-?[0-9]+\\.?[0-9]*$");
this.pattern = Pattern.compile(this.rgx);
this.setNouveauChiffre(true);
}
@Override
public String controleChiffre(String chiffre) {
/* Si le chiffre doit être négatif */
String strNegation = "";
if (this.isNegatif()) {
strNegation = "-";
this.setNegatif(false);
}
/* pour le premier chiffre, ou les chiffre juste après avoir appuyer sur un operateur */
if (this.isNouveauChiffre())
this.setChiffre(strNegation + chiffre);
else
this.setChiffre(strNegation + this.getChiffre() + chiffre);
this.setNouveauChiffre(false);
return this.getChiffre();
}
@Override
public void controleOp(String operateur) {
/* Si on appuie plusieurs fois sur un operateur à la suite (gestion des chiffres négatifs qui utilisent le même bouton) */
if ((this.isNouveauChiffre() && operateur != "-")
|| (this.isNouveauChiffre() && operateur == "-" && this.isNegatif())) {
throw new IllegalArgumentException("Erreur : formule incorrecte");
}
/* On gère les chiffres négatifs autrement qu les operateur */
if (this.isNouveauChiffre() && operateur == "-") {
this.setNegatif(true);
} else {
float nbr;
/* l'affichage du zero initial doit etre géré de facon particulière */
if (this.getChiffre() == null || this.getChiffre().isEmpty())
nbr = 0;
else
nbr = (Float.valueOf(this.getChiffre()));
/* On ne fait pas d'operation au premier appui sur un opérateur */
if (opPre != null) {
switch (opPre) {
case "+" -> this.getModel().operationAdditionner(nbr);
case "-" -> this.getModel().operationSoustraire(nbr);
case "/" -> this.getModel().operationDiviser(nbr);
case "*" -> this.getModel().operationMultiplier(nbr);
}
} else {
this.getModel().setRslt(nbr);
}
this.setOpPre(operateur);
this.setNouveauChiffre(true);
}
}
@Override
public void controleCancel() {
this.setNouveauChiffre(true);
this.setChiffre("0");
this.getModel().reset();
}
@Override
public void controleEgal() {
if (this.isNouveauChiffre()) {
throw new IllegalArgumentException("Erreur : formule incorrecte");
}
float nbr = (Float.valueOf(this.getChiffre()));
switch (this.getOpPre()) {
case "+" -> this.getModel().operationAdditionner(nbr);
case "-" -> this.getModel().operationSoustraire(nbr);
case "/" -> this.getModel().operationDiviser(nbr);
case "*" -> this.getModel().operationMultiplier(nbr);
}
this.setOpPre(null);
this.setNouveauChiffre(true);
this.setChiffre("0");
}
} |