Exercices
Utilisation du type HashMap
La classe HashMap
implante un dictionnaire qui permet
de retrouver un objet de type V
à partir d’une clef de type K
.
On a donc une classe avec deux paramètres-type.
Si vous avez réalisé l’exercice consistant à utiliser l’interface
(qui consiste à rechercher un Vehicule
à partir de sa référence)
package com.garaje.commons;
public interface CatalogueVehiculeSimple {
/**
* @param référence référence du véhicule cherché
* @return null si véhicule pas trouvé
*/
Vehicule get(String référence) ;
}
réaliser un autre "simulacre" (un code de test simplifié)
implantant cette interface et qui permette
de rechercher directement un Vehicule
par sa référence (utiliser un HashMap
).
Proposition de solution : Le catalogue de Vehicule (basé sur HashMap).
Définition de résultat de requête
Si vous avez réalisé l’exercice consistant à utiliser l’interface
(qui consiste à rechercher un Vehicule
à partir de sa référence)
CatalogueVehiculeSimple
ci-dessus ;
nous allons modifier cette interface de plusieurs manières:
-
Le critère de recherche de la méthode
get
est un "masque" de recherche sur la marque duVehicule
: c’est une chaine simple qui représente tout ou partie de la marque (par exemple "tro" pour "Citroën"). -
Le résultat est un ensemble de
Vehicule
s (plusieursVehicule
s peuvent avoir une marque qui correspond à ce critère de recherche). Quel type choisir pour représenter ce résultat? -
Une méthode permet d’obtenir tous les véhicules disponibles.
A partir de ces contraintes :
-
Définir une nouvelle version de l’interface
CatalogueVehicule
-
Réaliser un code simulacre qui implante cette interface.
Propositions de solution:
Définition d’une interface générique
Si vous avez réalisé l’exercice précédent (définition d’une interface pour le Catalogue de Vehicule) comment redéfinir cette interface de manière à ce que les services définis s’appliquent à un type quelconque? (on aurait alors la possibilité de définir un Catalogue de Livres, un Catalogue d’ArticleDeSport, etc….)
Proposition de solution:
Un Panier plus robuste
(Pour ceux qui ont commencé le projet de vente de livres)
Dans le projet "Oubangui.com" changer la réalisation du Panier
.
Au lieu d’utiliser un tableau de Livre
s utiliser une ArrayList
.
-
mettre en place les méthodes
ajouter(Livre l)
,retirer(Livre l)
etgetMontantTotal()
Une autre "vue" (Observer
) sur le Garage
En conservant le code précédent dans lequel le
garage
est un Observable
enregistrez un autre Observer
auprès du Garage
:
-
Celui-ci gérera des statistiques d’entrée (utiliser un
HashMap
): chaque fois que la "même" voiture entre au garage incrémenter un compteur ("même" signifie ici : même modèle). Faire une méthodetoString()
pour donner les statistiques générales. -
Tester
Un autre type de Garage
(Exercice de révision)
En reprenant les exercices de conception de la précédente leçon mettre en oeuvre la gestion d'événement personnalisée qui s’appuie sur cette interface d'écoute:
package com.grandgarage.biz;
public interface EcouteStationnement {
public void entrée(EvenementStationnement evt) ;
public void sortie(EvenementStationnement evt) ;
}
et sur cet événement:
package com.grandgarage.biz;
import java.util.EventObject;
public class EvenementStationnement extends EventObject {
public final Vehicule vehiculeConcerné ;
public final long estampilleHoraire = System.currentTimeMillis();
public EvenementStationnement(Stationnement stationnement, Vehicule voiture) {
super(stationnement) ;
this.vehiculeConcerné = voiture ;
}
/**
* cas très intéressant:
* <UL>
* <LI> covariance sur la méthode <TT>getSource()</TT>
* <LI> utiisation d'un champ protected de EventObject
* </UL>
* @return
*/
@Override
public Stationnement getSource() {
return (Stationnement) this.source ;
}
@Override
public String toString(){
//TODO : faire mieux!
return this.vehiculeConcerné.toString();
}
}
-
reécrire un Garage qui implante concrètement cette interface:
package com.grandgarage.biz;
public interface Stationnement {
public int garer(Vehicule vehicule) throws ExceptionContenance ;
public int retirer(Vehicule vehicule) ;
public int disponibilités() ;
}
et qui permet d’enregistrer des écouteurs.
(Utiliser une ArrayList
)
-
Tester en écrivant un
Vehicule
simple (commeMoto
) et un écouteur simple qui affiche le véhicule entré et le nombre de places libres.
Propositions de corrigés:
Exemples
Utilisation du type HashMap
package com.garaje.simulacres;
import com.garaje.commons.CatalogueVehiculeSimple;
import com.garaje.commons.Vehicule;
import com.garaje.deploy.Moto;
import com.garaje.deploy.Voiture;
import java.util.HashMap;
public class PseudoCatalogueSimple2 implements CatalogueVehiculeSimple {
static Vehicule[] tableauBidon = {
new Voiture("EZ44", "Wartburg", "1020", 425,220),
new Moto("HHX", "Mamuth", "986", 160, 120),
//etc, etc...
} ;
private HashMap<String,Vehicule> dict =
new HashMap<String,Vehicule>() ;
public PseudoCatalogueSimple2() {
for(Vehicule vehicule : tableauBidon) {
dict.put(vehicule.getRef(), vehicule) ;
}
}
@Override
public Vehicule get(String référence) {
return dict.get(référence );
}
}
Définition de résultat de requête
package com.garaje.commons;
import java.util.Iterator;
public interface CatalogueVehicule2 extends Iterable<Vehicule>{
// autres méthodes (voir par exemple CatalogueVehicule et critère de recherche)
Iterator<Vehicule> get(String masqueMarque);
}
package com.garaje.simulacres;
import com.garaje.commons.CatalogueVehicule2;
import com.garaje.commons.Vehicule;
import com.garaje.deploy.Moto;
import com.garaje.deploy.Voiture;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class PseudoCatalogue2 implements CatalogueVehicule2 {
static Vehicule[] tableauBidon = {
new Voiture("EZ44", "Wartburg", "1020", 425, 220),
new Moto("HHX", "Mamuth", "986", 160, 120), //etc, etc...
};
public Vehicule[] getVehicules() {
return tableauBidon ;
}
private List<Vehicule> liste = Arrays.asList(getVehicules());
@Override
public Iterator<Vehicule> get(String masqueMarque) {
ArrayList<Vehicule> res = new ArrayList<Vehicule>();
for (Vehicule vehicule : liste) {
// serait plus performant de simplement parcourir le tableau
// ceci est juste pour exemple
if (vehicule.getMarque().contains(masqueMarque)) {
res.add(vehicule);
}
}
return res.iterator();
}
@Override
public Iterator<Vehicule> iterator() {
return liste.iterator();
}
}
package com.garaje.ihm;
import com.garaje.commons.CatalogueVehicule2;
import com.garaje.commons.Vehicule;
import java.io.Console;
import java.util.Iterator;
/**
*
* Peut être reécrit avec interaction JSHELL
*/
public class SimpleIHMCatalogue2 { // implements Runnable!
private CatalogueVehicule2 catalogue ;
private Console console ;
public SimpleIHMCatalogue2(CatalogueVehicule2 catalogue) {
this.catalogue = catalogue;
this.console = System.console() ;
if(this.console == null ){
throw new RuntimeException("no Console!") ;
}
}
public void run() {
String question = null ;
while(null != (question = this.console.readLine("masque marque : "))) {
Iterator<Vehicule> trouvés = catalogue.get(question);
while(trouvés.hasNext()) {
this.console.printf("trouvé : %s\n", trouvés.next());
}
}
}
}
package com.garaje.tests;
import com.garaje.commons.CatalogueVehicule2;
import com.garaje.ihm.SimpleIHMCatalogue2;
import com.garaje.simulacres.PseudoCatalogue2;
/**
* p.e interaction JShell
*/
public class MainSimple2 {
public static void main(String[] args) {
CatalogueVehicule2 catalogue =
new PseudoCatalogue2() ;
SimpleIHMCatalogue2 ihm = new SimpleIHMCatalogue2(catalogue) ;
ihm.run() ;
}
}
Définition d’une interface générique
package com.garaje.commons;
import java.util.Iterator;
public interface Catalogue<T> extends Iterable<T> {
Iterator<T> get(String requête);
/*
* plus fort:
* Iterator<T> get(CritereChoix<T> critère) ;
* avec:
* public interface CritereChoix<X> {
* boolean choisir(X selection) ;
* public String toString() ;
* }
*/
}
Un Panier plus robuste
package com.oubangui.biz2;
import java.util.ArrayList;
import java.util.Collections;
public class Panier2 {
// MEMBRES : CHAMPS
// ID si persistant
//
// immuable, peut êre null
private Client client ;
//technical data
private ArrayList<Livre> contenu = new ArrayList<>();
// lire la doc de Collections!
private ArrayList<Livre> vueContenu = Collections.unmodifiableList(contenu) ;
// CONSTRUCTEURS
// cosntructeur par défaut ici
// MEMBRES : ACCESSEURS/MUTATEURS
public Client getClient() { return this.client ; }
public void setClient(Client cli) {
this.client = cli;
}
// MODIFICATEURS, SERVICES
public void ajouter(Livre livre) throws ExceptionStock {
livre.retirerDuStock(1);
// ATTENTION NON ATTEINT EN CAS DE PROPAGATION D'EXCEPTION
contenu.add( livre) ;
}
/**
* Pour simplifier: pas d'exception ou de résultat
* pour indiquer qu'on cherche à supprimer un Livre non présent
* dans le Panier.
* @param livre
*/
public void retirer(Livre livre) {
if(contenu.remove(livre)) {
livre.rajouterAuStock(1);
}
}
/**
* Dispositif critique pour ne pas casser l'encapsulation
*/
public ArrayList<Livre> getContenu() {
return vueContenu;
}
/**
* typiquement le montant total est un "attribut calculé".
* @return
*/
public double getMontantTotal() {
double res = 0. ;
for(Livre livre: contenu) {
res += livre.getPrix();
}
return res ;
}
@Override
public String toString(){
String res = " --- Panier ---\n";
// utiliser un StringBuilder!!
// ou plus simplement rajouter contenu.toString()
for(Livre bk : contenu){
res += bk.toString() + '\n' ;
}
return res ;
}
}
Une autre "vue" (Observer
) sur le Garage
package com.grandgarage.biz;
import java.util.HashMap;
import java.util.Observable;
import java.util.Observer;
import static java.awt.Color.*;
import static java.lang.System.Logger.Level.*;
public class StatsGarageD implements Observer {
private HashMap<String, Integer> stats = new HashMap<String, Integer>();
public void update(Observable arg0, Object arg1) {
EvenementGarage evt = (EvenementGarage) arg1;
String modèle = evt.véhicule.getModèle();
Integer nombre = stats.get(modèle);
switch (evt.mouvement) {
case SORTIE:
if (nombre != null) { // pour simplifier
// on ne fiat pas de controle de coherence
// on pourrait faire une assertion!)
stats.put(modèle, --nombre);
// on pourrait également détruire l'entrée si plus de voiture
// de ce modèle
}
break;
case ENTREE:
if (nombre == null) {
stats.put(modèle, Integer.valueOf(1));
} else {
// ATTENTION: autoboxing/unboxing! ne pas abuser!
stats.put(modèle, ++nombre);
}
break;
}
}
@Override
public String toString() {
return stats.toString();
}
public static void main(String[] args) {
try {
int taille = 50;
GarageD garage = new GarageD(taille);
garage.addObserver(new Panneau2GarageD());
StatsGarageD stats = new StatsGarageD();
garage.addObserver(stats);
garage.addObserver(new PanneauGarageD());
garage.garer(new VoitureV4("34RT34", "verso", 11567.56, GRAY));
// polymorphisme
VoitureV4 voiture = new VoitureAncienneV4("35RT34", "datsun", 11567.56, GRAY, 1945);
garage.garer(voiture);
garage.garer(new VoitureAncienneV4("33?RY45", "micra", 11567.56, GRAY, 1985));
System.out.println("Stats " + stats);
garage.retirer(voiture);
System.out.println("Stats " + stats);
} catch (ExceptionContenance ex) {
System.getLogger("com.grandgarage.biz").log(ERROR, "garage plein", ex);
}
}
}
Un autre type de Garage
package com.grandgarage.biz;
import java.util.ArrayList;
public class GarageVehicules implements Stationnement {
//TODO protéger contre les accès concurrents!!!
// sera un CopyOnWriteArrayList!
private ArrayList<EcouteStationnement> écouteurs =
new ArrayList<EcouteStationnement>() ;
private Vehicule[] parking;
private int nbVehicules;
private int tailleParking;
public GarageVehicules(int taille) {
//TODO on pourrait controler la taille !
this.tailleParking = taille;
parking = new Vehicule[taille];
}
public void addEcouteur(EcouteStationnement ecoute) {
écouteurs.add(ecoute) ;
}
public void removeEcouteur(EcouteStationnement ecoute){
écouteurs.remove(ecoute) ;
}
@Override
public int garer(Vehicule véhicule) throws ExceptionContenance {
// le parking est-il plein?
if (this.nbVehicules >= this.tailleParking) {
throw new ExceptionContenance(this, véhicule);
}
for (int index = 0; index < parking.length; index++) {
if (null == parking[index]) {
parking[index] = véhicule;
this.nbVehicules++;
EvenementStationnement evt = new EvenementStationnement(this, véhicule) ;
for(EcouteStationnement ecoute : écouteurs) {
ecoute.entrée(evt);
}
return index;
}
}
return -1; // anomalie!!!!
// on prévient les parties intéressées
}
@Override
public int retirer(Vehicule véhicule) {
for (int ix = 0; ix < parking.length; ix++) {
if (véhicule.equals(parking[ix])) {
parking[ix] = null;
nbVehicules--;
EvenementStationnement evt = new EvenementStationnement(this, véhicule) ;
for(EcouteStationnement ecoute : écouteurs) {
ecoute.sortie(evt);
}
return ix;
}
}
return -1;
}
@Override
public int disponibilités() {
return this.tailleParking - this.nbVehicules;
}
}
package com.grandgarage.biz;
import java.awt.Dimension;
public class Moto extends Vehicule {
public Moto(String reférence, String modèle, double prixHT, Dimension empattement) {
super(reférence, modèle, prixHT, empattement);
}
@Override
public double getTauxTVA() {
// TODO :lire dans une ressource
return 1.196 ;
}
@Override
public String getType() {
// un peu stupide!
return this.getClass().getSimpleName() ;
}
}
package com.grandgarage.biz;
public class AffichageStationnement implements EcouteStationnement {
@Override
public void entrée(EvenementStationnement evt) {
System.out.println(" ENTREE DE : " + evt);
System.out.println(" plus que : " + evt.getSource().disponibilités()
+ " place(s) libre(s)");
}
@Override
public void sortie(EvenementStationnement evt) {
System.out.println(" SORTIE DE : " + evt);
System.out.println(" plus que : " + evt.getSource().disponibilités()
+ " place(s) libre(s)");
}
}
package com.grandgarage.biz;
import java.awt.Dimension;
public class TestGarageVehicules {
public static void main(String[] args) throws Exception {
GarageVehicules garage = new GarageVehicules(30) ;
garage.addEcouteur(new AffichageStationnement());
Moto moto = new Moto("GHK235", "PowerGlide", 5789.78, new Dimension(70,145)) ;
garage.garer(moto );
garage.retirer(moto);
}
}