Vous êtes sur la page 1sur 11

Corrigé et Barème Contrôle de connaissances 2012/2013

des étudiants de 2è année (EI2)

CSC4002 : Contrôle Final Session 1

Date : vendredi 1 février 2013 — Durée : 1H30

Coordonnateurs : Christian Bac et Denis Conan

Les seuls documents autorisés sont ceux distribués en cours / BE / TP et mis à disposition
sur le site Web du module, ainsi que vos notes personnelles.

Notes en préambule :
— le travail doit se faire individuellement ;
— n’oubliez pas d’indiquer votre nom sur chaque feuille rendue ;
— soyez concis et précis, et justifiez vos réponses par des commentaires appropriés ;
— soyez rigoureux dans la syntaxe Java ;
— veillez à rendre une copie propre et lisible.
CF1 2012–2013

1 Étude de cas « Stratégies de tri »


Nous proposons l’analyse du cas d’étude « Stratégies de tri » que nous présentons ci-après
et qui démontre l’utilisation du patron de conception « Stratégie ».

Étude de cas. Le système dont le diagramme de classes est représenté en partie dans la
figure 1 consiste en l’organisation du tri de cubes selon différents critères. Un cube possède
quatre attributs privés : un nom qui est une chaîne de caractères, un poids qui est un double,
un volume qui est un double, et une stratégie qui est une référence sur un objet de type
StratégieDeTri.
Nous utilisons la façon de faire Java (c’est-à-dire un patron d’implantation ou idiome)
pour trier les objets contenus dans un tableau : méthode de classe sort de la classe Arrays. Le
code Java de la figure 3 montre un exemple d’utilisation de la méthode de classe sort de la
classe Arrays qui effectue un tri par ordre croissant. Pour être effective, la méthode sort utilise
la méthode compareTo implantée par la classe des objets à trier. Donc, pour être triable, une
classe doit implanter l’interface Comparable, comme indiqué dans le diagramme de classes de
la figure 1 : l’interface CubeTriable étend l’interface Comparable et la classe Cube implante
l’interface CubeTriable.
Le patron de conception « Stratégie » est représenté dans le diagramme de classes par
la classe abstraite StratégieDeTri et les classes TriAucun, TriParNom, TriParPoids, et TriPar-
Volume. Ce patron de conception utilise le concept d’interface pour permettre de choisir la
stratégie de tri ; chaque classe implantant l’interface réalise une stratégie. Le diagramme de
communication de la figure 2 montre une utilisation de l’algorithme de la méthode de tri
algorithmeDeTri. Après avoir vérifié que l’objet en argument est non null et de type Cube-
Triable, et avoir transformé par un downcast la référence obj en la référence o, la méthode
algorithmeDeTri est appelée.

Explications sur la conception Voici des éléments de description pour la réalisation :


— méthode compareTo de l’interface Comparable : cette méthode prend en argument un
Object et retourne un entier. Les deux objets doivent être comparables, c’est-à-dire
l’objet passé en argument est non null et est une instance (instanceof) de la même
classe que l’objet courant (this). La valeur retournée peut être :
— = 0 : l’objet courant est égal à l’objet passé en argument ;
— < 0 : l’objet courant est inférieur à l’objet passé en argument ;
— > 0 : l’objet courant est supérieur à l’objet passé en argument ;
— méthode algorithmeDeTri de la classe TriAucun : cette méthode retourne invariablement
l’entier 0. Par ailleurs, l’attribut nbAppelsTotal est incrémenté ;
— méthode algorithmeDeTri de la classe TriParNom : comme montré dans le diagramme
de communication de la figure 2, cette méthode retourne le résultat de la méthode
compareTo sur les noms des deux objets Cube. Par ailleurs, non montré explicitement
dans le diagramme de communication, l’attribut nbAppelsTotal est incrémenté ;
— méthode algorithmeDeTri de la classe TriParPoids : fonctionne de manière similaire à la
méthode de même nom de la classe TriParNom, avec l’attribut poids ;
— méthode algorithmeDeTri de la classe TriParVolume : fonctionne de manière similaire à
la méthode de même nom de la classe TriParNom, avec l’attribut volume ;

Les questions suivantes permettent d’implanter le système. Comme montré dans le code
de la méthode main de la classe Main, toutes les classes font partie du paquetage stratégie.

Télécom SudParis — Denis Conan et Christian Bac — 1 février 2013 — CSC4002 2


CF1 2012–2013

Questions
Question 1 [2 pts] : en étudiant le code de la classe main de la classe Main dans la figure 3,
répondez très succinctement aux questions qui suivent :
1. que signifie le mot-clef static de la méthode main ?
2. pourquoi le mot-clef static est obligatoire pour la méthode display ?
3. combien d’objets de type StratégieDeTri sont créés dans la méthode main ?
4. ré-écrivez l’une des boucles for sous une autre forme.

Réponse:

1. static = méthode de classe

2. pas d’objet de la classe Main

3. 4 (constructeur cube, tris aucun) + 4 (tris par nom) + 4 (tris par


volume) + 4 (tris par poids) = 16 instances

4. for (int i = 0; i < cubes.length; i++) {...}

Erreurs fréquemment observées :



Barème de correction sur 2 point(s) :
Répartition :
0,5 par question

Question 2 [3 pts] : écrivez tout le code de l’interface CubeTriable.

Réponse:

package strategie ;
public interface CubeTriable extends Comparable < Object > {
public StrategieDeTri g etStrategieD eTri ();
public void setStra tegieD eTri ( StrategieDeTri s );
public String getNom ();
public double getPoids ();
public double getVolume ();
}

Erreurs fréquemment observées :



Barème de correction sur 3 point(s) :
Répartition :
0,5 extends Comparable
0,5 uniquement des déclarations de méthodes
0,5 quatre méthodes (acception stricte, classe abstraite) ou cinq

Télécom SudParis — Denis Conan et Christian Bac — 1 février 2013 — CSC4002 3


CF1 2012–2013

méthodes (acception plus large, avec classes enfants)


0,5 tous les bons prototypes
0,5 tout public

Question 3 [6 pts] : écrivez tout le code de la classe Cube.


Dans cette question, les cas d’erreur ne lèvent pas d’exception.

Réponse:

package strategie ;
public class Cube implements CubeTriable {
private String nom ;
private double poids ;
private double volume ;
private StrategieDeTri strategie ;
public Cube ( String n , double p , double v , StrategieDeTri s ) {
nom = n ;
poids = p ;
volume = v ;
strategie = s ;
}
public String toString () {
return (" Le cube de nom ‘" + nom + " ’ pese " + poids
+ " kg pour un volume de " + volume + " m3 .");
}
public int compareTo ( Object ob ) {
if ( ob != null ) {
if ( ob instanceof CubeTriable ) {
CubeTriable o = ( CubeTriable ) ob ;
if ( strategie != null ) {
return strategie . algorithmeDeTri ( this , o );
}
}
}
return 0;
}
public StrategieDeTri g etStrategieD eTri () {
return strategie ;
}
public void setStra tegieD eTri ( StrategieDeTri s ) {
strategie = s ;
}
public String getNom () {
return nom ;
}
public double getPoids () {
return poids ;
}
public double getVolume () {
return volume ;
}
}

Erreurs fréquemment observées :

Télécom SudParis — Denis Conan et Christian Bac — 1 février 2013 — CSC4002 4


CF1 2012–2013


Barème de correction sur 6 point(s) :
Répartition :
2
0,5 public class
0,5 implements CubeTriable
0,5 attributs nom, poids, volume (private et types)
0,5 attribut stratégie (private et type)
2
0,5 prototype constructeur
0,5 corps constructeur
0,5 toString (indices dans la visualisation d’une exécution)
0,5 les getters et le setter
2 compareTo (indices dans le diagramme de communication)
0,5 test null
0,5 test instanceof
0,5 downcast
0,5 return stratégie.algorithmeDeTri

Question 4 [4 pts] : écrivez tout le code de la classe abstraite StratégieDeTri et des classes
TriAucun et TriParNom.

Réponse:

package strategie ;
public abstract class StrategieDeTri {
protected int nbAppelsTotal = 0;
public abstract int algorithmeDeTri ( CubeTriable a , CubeTriable b );
}

package strategie ;
public class TriAucun extends StrategieDeTri {
public int algorithmeDeTri ( CubeTriable a , CubeTriable b ) {
super . nbAppelsTotal ++;
return 0;
}
}

package strategie ;
public class TriParNom extends StrategieDeTri {
public int algorithmeDeTri ( CubeTriable a , CubeTriable b ) {
super . nbAppelsTotal ++;
return a . getNom (). compareTo ( b . getNom ());
}
}

Erreurs fréquemment observées :



Barème de correction sur 4 point(s) :

Télécom SudParis — Denis Conan et Christian Bac — 1 février 2013 — CSC4002 5


CF1 2012–2013

Répartition :
0,5 classe abstraite StratégieDeTri
0,5 méthode abstraite algorithmeDeTri
0,5 attribut nbAppelsTotal protégé et initialisé à 0
0,5 extends StratégieDeTri dans les classes TriAucun et TriParNom
0,5 super.nbAppelsTotal++ dans les classes TriAuncun et TriParNom
0,5 return 0 dans la classe TriAucun
1 return a.getNom().compareTo(b.getNom()) dans la classe TriparNom
0,5 getNom
0,5 compareTo

Question 5 [2 pt] : donnez une nouvelle version de la définition de la méthode compareTo


de la classe Cube en levant une exception de type ClassCastException dans les cas
d’erreur : argument null et argument qui n’est pas un CubeTriable. Supposez que la
classe ClassCastException existe.

Réponse:

package strategie ;
public class CubeAvec Except ion implements CubeTriable {
private String nom ;
private double poids ;
private double volume ;
private StrategieDeTri strategie ;
public CubeAve cExcep tion ( String n , double p , double v , StrategieDeTri s ) {
nom = n ;
poids = p ;
volume = v ;
strategie = s ;
}
public String toString () {
return (" Le cube de nom ’" + nom + " ’ pese " + poids
+ " kg pour un volume de " + volume + " m3 .");
}
public int compareTo ( Object ob ) throws ClassCastException {
if ( ob != null ) {
if ( ob instanceof CubeTriable ) {
CubeTriable o = ( CubeTriable ) ob ;
return strategie . algorithmeDeTri ( this , o );
}
throw new ClassC as tException (" pas le bon type ");
}
throw new C la ssCas tE xcepti on (" argument null ");
}
public StrategieDeTri g etStrategieD eTri () {
return strategie ;
}
public void setStra tegieD eTri ( StrategieDeTri s ) {
strategie = s ;
}
public String getNom () {
return nom ;
}
public double getPoids () {
return poids ;
}

Télécom SudParis — Denis Conan et Christian Bac — 1 février 2013 — CSC4002 6


CF1 2012–2013

public double getVolume () {


return volume ;
}
}

Barème de correction sur 2 point(s) :


Répartition :
0,5 throws
1 throw
0,5 new ClassCastException avec un message en paramètre

Question 6 [2 pts] : écrivez, en utilisant JUnit et en vous inspirant d’une partie du scénario
de la méthode main de la classe Main, un test de validation permettant de tester que
les tris réalisés correspondent au jeu de données d’entrée. Par exemple, quatre cubes
utilisent la stratégie de tri par poids, chaque cube possède un poids différent, et le tri
est correct.
Dans cette question, vous pouvez utiliser la méthode de classe assertEquals de la classe
Assert avec deux arguments de type Object.

Réponse:

package strategie ;
import java . util . Arrays ;

import org . junit . Assert ;


import org . junit . Test ;
public class JUnitCubeTest {
@Test
public void test () {
CubeTriable d1 = new Cube (" a " , 4.0 , 1.0 , new TriParPoids ());
CubeTriable d2 = new Cube (" b " , 3.0 , 3.0 , new TriParPoids ());
CubeTriable d3 = new Cube (" c " , 2.0 , 2.0 , new TriParPoids ());
CubeTriable d4 = new Cube (" d " , 1.0 , 3.0 , new TriParPoids ());
CubeTriable [] cubes = { d1 , d2 , d3 , d4 };
Arrays . sort ( cubes );
Assert . assertEquals ( d4 , cubes [0]);
Assert . assertEquals ( d3 , cubes [1]);
Assert . assertEquals ( d2 , cubes [2]);
Assert . assertEquals ( d1 , cubes [3]);
}
}

Erreurs fréquemment observées :



Barème de correction sur 2 point(s) :
Répartition :

Télécom SudParis — Denis Conan et Christian Bac — 1 février 2013 — CSC4002 7


CF1 2012–2013

0,5 annotation @Test


0,5 scénario correct (TriParPoids partout)
0,5 assertEquals d4 et cubes[0], etc.
0,5 méthode de classe Assert.assertEquals

Question 7 [1 pt] : dans la méthode main de la classe Main, observez que rien n’interdit que
d1 utilise la stratégie TriParPoids, et que d2, d3 et d4 utilisent la stratégie TriParNom.
Proposez une solution simple pour éviter le risque d’erreur provenant d’un tri inco-
hérent car différentes stratégies de tris sont utilisées. En d’autres termes, modifiez la
classe Cube pour qu’à un instant donné tous les cubes utilisent la même stratégie de
tri.

Réponse:

attribut de classe stratégie

Erreurs fréquemment observées :



Barème de correction sur 1 point(s) :
Répartition :
1 static stratégie

Télécom SudParis — Denis Conan et Christian Bac — 1 février 2013 — CSC4002 8


CF1 2012–2013

<<interface>> <<interface>> <<abstract>>


java.lang.Comparable CubeTriable StratégieDeTri
#nbAppelsTotal : int =0
+compareTo(Object ob): int +getStrategieDeTri(): +<<abstract>>algorithmeDeTri(
StrategieDeTri CubeTriable a, CubeTriable b): int
* +setStrategieDeTri(
StrategieDeTri s)
+getNom(): String
+getPoids(): double TriAucun
+getVolume(): double

Main +algorithmeDeTri(
CubeTriable a, CubeTriable b): int

+main(String[] args)
TriParNom
+display(CubeTriable[] cubes)
Cube
+algorithmeDeTri(
CubeTriable a, CubeTriable b): int
− nom : String
− poids : double
− volume : double TriParPoids
+constructeur(String nom,
double poids, double volume,
+algorithmeDeTri(
StratégieDeTri s) CubeTriable a, CubeTriable b): int
+toString(): String
// liste des autres méthodes
...

TriParVolume

+algorithmeDeTri(
CubeTriable a, CubeTriable b): int

Figure 1 – Diagramme de classes.

compareTo(obj): int
2:r=algorithmeDeTri(c, o): int [o != null]
:TriParNom c:Cube
2.1:nc=getNom():String

2.2:no=getNom():String

1:o=(CubeTriable) obj [obj != null ET obj instanceof CubeTriable]

o:Cube

Figure 2 – Diagramme de communication de la méthode compareTo de la classe Cube lorsque le tri est
effectué avec un objet de classe TriParNom.

Télécom SudParis — Denis Conan et Christian Bac — 1 février 2013 — CSC4002 9


CF1 2012–2013

package strategie ;
import java . util . Arrays ;
public class Main {
public static void main ( String [] arg ) {
CubeTriable d1 = new Cube (" a " , 4.0 , 1.0 , new TriAucun ());
CubeTriable d2 = new Cube (" b " , 3.0 , 3.0 , new TriAucun ());
CubeTriable d3 = new Cube (" c " , 2.0 , 2.0 , new TriAucun ());
CubeTriable d4 = new Cube (" d " , 1.0 , 3.0 , new TriAucun ());
CubeTriable [] cubes = { d1 , d2 , d3 , d4 };
System . out . println (" Liste d ’ origine :");
display ( cubes );
Arrays . sort ( cubes );
System . out . println ();
System . out . println (" Liste des cubes , tri par defaut :");
display ( cubes );
for ( CubeTriable c : cubes ) {
c . setStr ategie DeTri ( new TriParNom ());
}
Arrays . sort ( cubes );
System . out . println ();
System . out . println (" Liste des cubes , tri par nom :");
display ( cubes );
for ( CubeTriable c : cubes ) {
c . setStr ategie DeTri ( new TriParVolume ());
}
Arrays . sort ( cubes );
System . out . println ();
System . out . println (" Liste des cubes , tri par volume :");
display ( cubes );
for ( CubeTriable c : cubes ) {
c . setStr ategie DeTri ( new TriParPoids ());
}
Arrays . sort ( cubes );
System . out . println ();
System . out . println (" Liste des cubes , tri par poids :");
display ( cubes );
}
public static void display ( CubeTriable [] cubes ) {
for ( CubeTriable c : cubes ) {
System . out . println (" " + c );
}
}
}

Figure 3 – Code Java de la classe Main

Télécom SudParis — Denis Conan et Christian Bac — 1 février 2013 — CSC4002 10


CF1 2012–2013

Liste d’origine:
Le cube de nom ‘a’ pese 4.0kg pour un volume de 1.0m3.
Le cube de nom ‘b’ pese 3.0kg pour un volume de 3.0m3.
Le cube de nom ‘c’ pese 2.0kg pour un volume de 2.0m3.
Le cube de nom ‘d’ pese 1.0kg pour un volume de 3.0m3.

Liste des cubes, tri par defaut:


Le cube de nom ‘a’ pese 4.0kg pour un volume de 1.0m3.
Le cube de nom ‘b’ pese 3.0kg pour un volume de 3.0m3.
Le cube de nom ‘c’ pese 2.0kg pour un volume de 2.0m3.
Le cube de nom ‘d’ pese 1.0kg pour un volume de 3.0m3.

Liste des cubes, tri par nom:


Le cube de nom ‘a’ pese 4.0kg pour un volume de 1.0m3.
Le cube de nom ‘b’ pese 3.0kg pour un volume de 3.0m3.
Le cube de nom ‘c’ pese 2.0kg pour un volume de 2.0m3.
Le cube de nom ‘d’ pese 1.0kg pour un volume de 3.0m3.

Liste des cubes, tri par volume:


Le cube de nom ‘a’ pese 4.0kg pour un volume de 1.0m3.
Le cube de nom ‘c’ pese 2.0kg pour un volume de 2.0m3.
Le cube de nom ‘b’ pese 3.0kg pour un volume de 3.0m3.
Le cube de nom ‘d’ pese 1.0kg pour un volume de 3.0m3.

Liste des cubes, tri par poids:


Le cube de nom ‘d’ pese 1.0kg pour un volume de 3.0m3.
Le cube de nom ‘c’ pese 2.0kg pour un volume de 2.0m3.
Le cube de nom ‘b’ pese 3.0kg pour un volume de 3.0m3.
Le cube de nom ‘a’ pese 4.0kg pour un volume de 1.0m3.

Figure 4 – Exemple d’exécution de la classe Main

Télécom SudParis — Denis Conan et Christian Bac — 1 février 2013 — CSC4002 11