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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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 : Sélectionner tout - Visualiser dans une fenêtre à part
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"); } }
Partager