0% ont trouvé ce document utile (0 vote)
974 vues19 pages

Corrigés Des Exercices: Exercice: Singleton/journalisation D'un Compte Bancaire

Ce document décrit l'implémentation d'une application bancaire simple utilisant les patterns Singleton et Multiton pour la journalisation des opérations sur les comptes. La classe Journalisation permet de tracer les événements en une seule instance avec Singleton, puis en deux instances distinctes avec Multiton pour séparer les opérations validées des refusées.

Transféré par

Lotfi Gana
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
974 vues19 pages

Corrigés Des Exercices: Exercice: Singleton/journalisation D'un Compte Bancaire

Ce document décrit l'implémentation d'une application bancaire simple utilisant les patterns Singleton et Multiton pour la journalisation des opérations sur les comptes. La classe Journalisation permet de tracer les événements en une seule instance avec Singleton, puis en deux instances distinctes avec Multiton pour séparer les opérations validées des refusées.

Transféré par

Lotfi Gana
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

www.djouabri.

com
[email protected]

Corrigés des Exercices


Exercice : Singleton/journalisation d’un compte bancaire
Exercice : Singleton/journalisation d’un compte bancaire
Description du problème
Afin de mettre en pratique le pattern Singleton en Java, prenons un
court exemple d’implémentation dans le milieu bancaire. Tout
d’abord nous allons concevoir une classe CompteBancaire qui
permet de déposer ou retirer de l’argent sur un compte. Mais nous
souhaiterions pouvoir afficher les opérations (effectuées ou refusées)
dans la console en cas de litige (il serait aussi possible d’utiliser en
sortie un fichier texte). Cette petite application devra rapidement
évoluer et il est fort probable que par la suite d’autres classes soient
concerner par cette journalisation. Pour cela, nous allons
implémenter une classe distincte nommée Journalisation reprenant le
pattern Singleton. Ainsi nous allons garantir que notre programme va
utiliser une seule et même instance de la classe Journalisation. Une
troisième classe intitulée Main permettra d’exécuter l’application et
d’obtenir un résultat en console.
Implémentation de la solution basée sur Singleton
Implémentation de la classe Journalisation
// Classe basée sur le pattern Singleton qui permet la journalisation de l'application.
public class Journalisation
{
private static Journalisation uniqueInstance;// Stockage de l'unique instance de cette classe.
private String log;// Chaine de caractères représentant les messages de log.

// Constructeur en privé (donc inaccessible à l'extérieur de la classe).


private Journalisation()
{
log = new String();
}

// Méthode statique qui sert de pseudo-constructeur (utilisation du mot clef "synchronized" pour le multithread).
public static synchronized Journalisation getInstance()
{
if(uniqueInstance==null)
{
uniqueInstance = new Journalisation();
}
return uniqueInstance;
}

// Méthode qui permet d'ajouter un message de log.


public void ajouterLog(String log)
{
// On ajoute également la date du message.
Date d = new Date();
DateFormat dateFormat = new SimpleDateFormat("dd/MM/yy HH'h'mm");
this.log+="["+dateFormat.format(d)+"] "+log+"\n";
}

// Méthode qui retourne tous les messages de log.


public String afficherLog()
{
return log;
}
}
Implémentation de la classe Journalisation

L’attribut uniqueInstance permet de stocker l’unique instance de


cette classe. Le constructeur est déclaré privé donc accessible
uniquement depuis la classe elle même. C’est la méthode
getInstance() qui permet d’instancier cette classe. Pour que notre
application fonctionne dans le cas du multithread nous avons utilisé
le mot clef « synchronized » [1] dans la déclaration de
getInstance(). Plus classiquement la méthode ajouterLog(string)
permet d’ajouter un message dans l’attribut log et afficherLog()
retourne le contenu de cet attribut.
Implémentation de la classe CompteBancaire
// Classe représentant un compte bancaire simpliste.
public class CompteBancaire
{
private int numero;// Numéro du compte.
private double solde;// Argent disponible sur le compte.

// Constructeur d'un CompteBancaire à partir de son numéro.


public CompteBancaire(int numero)
{
this.numero=numero;
this.solde=0.0;
}

// Méthode qui permet de déposer de l'argent sur le compte.


public void deposerArgent(double depot)
{
if(depot>0.0)
{
solde+=depot;// On ajoute la somme déposée au solde.
Journalisation.getInstance().ajouterLog("Dépôt de "+depot+"€ sur le compte "+numero+".");
}
else
{
Journalisation.getInstance().ajouterLog("/!\\ Dépôt d'une valeur négative impossible ("+numero+").");
}
}

// Méthode qui permet de retirer de l'argent sur le compte.


public void retirerArgent(double retrait)
{
if(retrait>0.0)
{
if(solde>=retrait)
{
solde-=retrait;// On retranche la somme retirée au solde.
Journalisation.getInstance().ajouterLog("Retrait de "+retrait+"€ sur le compte "+numero+".");
}
else
{
Journalisation.getInstance().ajouterLog("/!\\ La banque n'autorise pas de découvert ("+numero+").");
}
}
else
{
Journalisation.getInstance().ajouterLog("/!\\ Rerait d'une valeur négative impossible ("+numero+").");
}
}
}
Implémentation de la classe CompteBancaire

La classe CompteBancaire correspond à un compte. Celui-ci


possède un numéro (identifiant) et un solde. Il est possible de
déposer de l’argent ou d’en retirer grâce aux méthodes
deposerArgent(double) et retirerArgent(double). De plus,
certaines vérifications sont effectuées notamment pour éviter un
découvert (notre banque ne fait pas crédit). Ces deux dernières
méthodes utilisent la classe Journalisation pour tracer les
opérations. On remarque les appels à la méthode getInstance()
pour obtenir une instance unique de cette classe.
Implémentation de la classe Main
// Classe principale de l'application.
public class Main
{
// Méthode principale.
public static void main(String[] args)
{
// Création et utilisation du CompteBancaire cb1.
CompteBancaire cb1 = new CompteBancaire(123456789);
cb1.deposerArgent(100);
cb1.retirerArgent(80);
// Création et utilisation du CompteBancaire cb2.
CompteBancaire cb2 = new CompteBancaire(987654321);
cb2.retirerArgent(10);
// Affichage des logs en console.
String s = Journalisation.getInstance().afficherLog();
System.out.println(s);
}

}
Implémentation de la classe Main
La classe Main est la classe principale de notre programme. Elle va permettre d’exécuter un
exemple et d’afficher son résultat en sortie. En effet, sur le compte numéro 123456789 on
va déposer 100€ et retirer 80€. Puis sur le compte 987654321 on va retirer 10€ (alors qu’il
n’y a pas d’argent sur ce compte).

Résultat en console
[30/04/07 13h46] Dépôt de 100.0€ sur le compte 123456789.
[30/04/07 13h46] Retrait de 80.0€ sur le compte 123456789.
[30/04/07 13h46] /!\ La banque n'autorise pas de découvert (987654321).

Le résultat obtenu est conforme à notre attente. On constate que tous les messages
ont été ajoutés à une seule instance de Journalisation.
Extension du problème

Notre application fonctionne à merveille, mais le


banquier nous fait remonter un souci. La banque dispose
de beaucoup de clients et il est difficile d’isoler les
messages concernant les opérations effectuées des
messages concernant les opérations refusées. Or les
messages confirmant une opération sont utilisés à des
fin de statistiques alors que les messages concernant les
opérations refusées doivent être étudiés plus en détails.
Pour séparer ces deux types de messages nous allons
nous servir du pattern Multiton.
Implémentation de la solution basée sur Multiton
Implémentation de la solution basée sur Multiton

Le diagramme UML du Multiton diffère peu de


celui du Singleton. On retrouve le
constructeur en privé et le pseudo-
constructeur getInstance(). En revanche
l’attribut nommé instances est de type table
de hashage et peut donc contenir plusieurs
instances de Journalisation. La structure de la
classe CompteBancaire est identique à celle
présente.
Partie modifiée de l’implémentation de la classe
Journalisation
//Classe basée sur le pattern Singleton qui permet la journalisation de l'application.
public class Journalisation
{
private static HashMap instances = new HashMap();// Table de hashage d'instance (clef, valeur).
private String log;// Chaine de caractères représentant les messages de log.

// Constructeur en privé (donc inaccessible à l'extérieur de la classe).


private Journalisation()
{
log = new String();
}

// Méthode statique qui sert de pseudo-constructeur (utilisation du mot clef "synchronized" pour le multithread).
public static synchronized Journalisation getInstance(String clef)
{
Journalisation inst = instances.get(clef);
if (inst == null)
{
inst = new Journalisation();
instances.put(clef, inst);
}
return inst;
}
//...
}
Partie modifiée de l’implémentation de la classe
Journalisation

Voici les modifications apportées à la classe


Journalisation pour répondre au pattern Multiton. A
la place d’un attribut contenant l’unique instance de
Jounalisation on place une table de hashage. Ainsi
on peut stocker plusieurs instances chacune
identifiée par une clef. On peut donc obtenir une
instance pour les opérations effectuées et une
instance pour les opérations refusées.
Partie modifiée de l’implémentation de la classe CompteBancaire
//Classe représentant un compte bancaire simpliste.
public class CompteBancaire
{
//...

// Méthode qui permet de déposer de l'argent sur le compte.


public void deposerArgent(double depot)
{
if(depot>0.0)
{
solde+=depot;// On ajoute la somme déposée au solde.
Journalisation.getInstance("informations").ajouterLog("Dépôt de "+depot+"€ sur le compte "+numero+".");
}
else
{
Journalisation.getInstance("erreurs").ajouterLog("/!\\ Dépôt d'une valeur négative impossible ("+numero+").");
}
}

// Méthode qui permet de retirer de l'argent sur le compte.


public void retirerArgent(double retrait)
{
if(retrait>0.0)
{
if(solde>=retrait)
{
solde-=retrait;// On retranche la somme retirée au solde.
Journalisation.getInstance("informations").ajouterLog("Retrait de "+retrait+"€ sur le compte "+numero+".");
}
else
{
Journalisation.getInstance("erreurs").ajouterLog("/!\\ La banque n'autorise pas de découvert ("+numero+").");
}
}
else
{
Journalisation.getInstance("erreurs").ajouterLog("/!\\ Rerait d'une valeur négative impossible ("+numero+").");
}
}
}
Partie modifiée de l’implémentation de la classe CompteBancaire

Les modifications de CompteBancaire concerne


l’implémentation des méthodes
deposerArgent(double) et
retirerArgent(double). En effet, maintenant
que nous gérons deux instances il faut
spécifier l’instance dans laquelle le message
doit être stocké.
Implémentation de la classe Main

//Classe principale de l'application.


public class Main
{
// Méthode principale.
public static void main(String[] args)
{
// Création et utilisation du CompteBancaire cb1.
CompteBancaire cb1 = new CompteBancaire(123456789);
cb1.deposerArgent(100);
cb1.retirerArgent(80);
// Création et utilisation du CompteBancaire cb2.
CompteBancaire cb2 = new CompteBancaire(987654321);
cb2.retirerArgent(10);
// Affichage des logs "informations" en console.
String s = Journalisation.getInstance("informations").afficherLog();
System.out.println("Informations :\n"+s);
// Affichage des logs "erreurs" en console.
s = Journalisation.getInstance("erreurs").afficherLog();
System.out.println("Erreurs :\n"+s);
}

}
Implémentation de la classe Main
Retouchons notre classe Main pour afficher les modifications dans la console. En
effet, nous allons afficher distinctement les informations (opérations réussies) des
erreurs (opérations ayant échouées).
Résultat en console

Informations :
[30/04/07 13h48] Dépôt de 100.0€ sur le compte 123456789.
[30/04/07 13h48] Retrait de 80.0€ sur le compte 123456789.

Erreurs :
[30/04/07 13h48] /!\ La banque n'autorise pas de découvert
(987654321).

Le résultat obtenu est conforme aux souhaits du banquier. Pour cela on a utilisé
deux instances de Journalisation une gérant les informations l’autre les erreurs.
Conclusion
L’implémentation du pattern Singleton en Java est
relativement simple. Il en va de même pour le pattern
Multiton. Attention tout de même à garder à l’esprit que le
pattern Multiton tel qu’il est présenté ici ne permet pas de
garantir un nombre maximum d’instances. En effet, il suffit
d’utiliser une nouvelle clef pour créer une nouvelle instance.
On remarque également que le passage du pattern Singleton
à Multiton engendre des modifications dans toutes les parties
de l’application utilisant la classe. Mieux vaut donc bien
réfléchir avant de choisir le pattern Singleton ou Multiton.
Maintenant que vous avez compris le principe vous pouvez
adapter ces patterns à des besoins spécifiques.

Vous aimerez peut-être aussi