Cours Approche Objet

Transcription

Cours Approche Objet
Cours Approche Objet
Lionel Clément
2016-2017
Table des matières
1 Introduction
1.1 Bribes de l’histoire de la programmation objet . . . . . . . . . . . . . . . . . . . . .
2 Objet
2.1 Trio <entité, attribut, valeur> . . . . . . .
2.2 Envoi de message . . . . . . . . . . . . . . .
2.3 Objet composite . . . . . . . . . . . . . . .
2.4 Objet agrégés ou associés . . . . . . . . . .
2.5 Objets dépendants . . . . . . . . . . . . . .
2.6 Encapsulation des attributs . . . . . . . . .
2.7 Encapsulation des méthodes . . . . . . . . .
2.8 Création et suppression d’objets . . . . . .
2.8.1 Ramasse-miettes (garbage collector )
2.9 Cohésion et couplage . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4
4
5
5
5
5
8
12
16
16
16
16
18
3 Classe
18
3.1 Instanciation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.2 Héritage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4 Types abstraits de données (ADT) et classes
20
4.1 Modularité . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5 Polymorphisme
23
5.0.1 Héritage multiple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
6 Interface Homme-Machine
36
6.1 MVC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
7 Design Patterns
7.1 Introduction . . .
7.2 Singleton . . . .
7.3 Abstract Factory
7.4 Adapter . . . . .
7.5 Template method
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
37
37
46
47
49
50
7.6
7.7
State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
Observer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
8 Exceptions
58
8.1 Exceptions en Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
9 Clonage
64
10 Multi-tâches
67
11 Tests
69
Informations administratives
— Code UE : 4TIN706U
— Cours : Amphi 1 Bât. A9 – Mardi 14 :00-16 :00 (6/09, 13/09, 20/09, 27/09, 4/10, 11/10,
18/10, 25/10, 8/11, 15/11, 22/11, 29/11)
— 4 groupes de TDs :
— Lundi 16 :15-18 :15
— Mardi 16 :15-18 :15
— Mercredi 08 :00-10 :00
— Vendredi 08 :00-10 :00
— Contrôle des connaissances
— 6 ECTS (environ 150 à 180 heures de travail)
— Examen écrit 3h00 coef. 2/3
— Contrôle continu 1/3 (deux notes : un TP noté, un DS)
Prérequis
— Connaissance de la programmation impérative
— Première utilisation d’un langage de programmation à objet (Java, C++, C#, Python, Php,
Javascript, etc.)
Objectifs
— Comprendre le concept de programmation objet
— Concepts avancés : exceptions, clonage, classes génériques, collections, itérations, classes
internes...
— Savoir développer une interface homme-machine
— Appliquer des modèles de conception
— Savoir tester les programmes
Références bibliographiques
— Joshua Bloch, ”Effective Java, Programming Language Guide”, Addison-Wesely 2001
2
— Maurice Naftalin et Philip Wadler, ”Java Generics and Collections”, O’Reilly 2006
— E. Gamma, R. Helm, R. Johnson et J. Vlissides, ”Design Patterns. Catalogue de modèles
de conception réutilisables”, Vuibert, 1999
3
1
Introduction
Un programme informatique développé avec un langage de programmation impératif récent est
modulaire et structuré. Cela suffit-il pour envisager de l’utiliser sur de très gros projets ?
Quels sont les problèmes qu’on rencontre avec un logiciel développé sans l’approche objet ?
Prenons le cas du développement d’un jeu vidéo : PacMan (petit rappel du jeu pour ceux qui
ne connaissent pas)
— Est-on certain d’avoir réutilisé tout le code existant ?
Exemple : Une procédure permettant à un personnage du jeu de se déplacer, peut-elle
s’appliquer à tous les personnages ? La procédure pourra éventuellement être différente pour
un personnage qui fuit, un autre qui attaque ou le joueur. Pourtant les deux doivent éviter
les obstacles de la même manière. Comment être certain que cette stratégie d’évitement
convient aux deux types de personnages ?
— Peut-on tester tout le code ?
Exemple : Si on teste l’évitement d’obstacle pour un personnage qui attaque, un autre qui
fuit et enfin le joueur, doit-on écrire trois procédures de test ou une seule ?
— Peut-on organiser le développement de l’ensemble du jeu par une équipe en se partageant
les tâches ?
Exemple : Celui ou celle qui développe la procédure d’évitement des obstacles, peut-il le faire
indépendamment de celui qui écrit la stratégie d’attaque ou de fuite dans le labyrinthe ?
— Peut-on reprendre une partie du code dans le cas d’une refonte importante ?
Exemple : La demande est de porter le jeu pour une autre plateforme en utilisant une bibliothèque graphique différente. La partie graphique du jeu est-elle suffisamment indépendante
pour que l’ensemble du code ne soit pas repris ?
— Peut-on distribuer le code facilement ?
Exemple : Le code est documenté et confié en logiciel libre à la communauté. Est-il simple
de faire des modifications, des ajouts pour améliorer le jeu en s’assurant qu’il est toujours
exempt de bugs ?
Quiconque a développé un projet un peu ambitieux avec un langage de programmation non
objet, sait qu’il est difficile, voire impossible de répondre favorablement à ces différentes questions.
D’autre part, regrouper en entités uniques les propriétés d’un même concept permet de concevoir
de façon très différente un projet.
1.1
Bribes de l’histoire de la programmation objet
Dans les années 60, la programmation connait une période où l’on structure les programmes
— Algol 58, 60, 68 (1958-1975)
— Pascal (1971)
A la fin des années 60, on voit émerger le premier langage orienté objet :
— Simula I (1962) est destiné aux problèmes de simulation. C’est un sur-ensemble d’Algol qui
intègre un mécanisme à événements discrets. C’est le premier langage qui regroupe sous une
même entité données et procédures.
— Simula (1967) est le premier véritable langage de programmation orienté objet.
Un programme est un ensemble d’objets qui sont autonomes et disposent de leurs propres
données et procédures. Ceci permet de simuler des comportements parallèles.
4
Simula intègre la notion d’héritage. Les notions d’encapsulation et l’abstraction des données
réhabilite la fusion des données et des programmes. Contredisant un principe fort de la
programmation structurée des années 70-80. Ada et CLU sont issues de cette école.
Simula a servi comme modèle pour un ensemble de langages de programmation à typage
statique dite de l’école scandinave (C++, Clascal, Object Pascal, Eiffel, Beta).
— Smalltalk-72, Smalltalk-76, Smalltalk-80
Smalltalk généralise la notion d’objet qui devient le seul élément de programmation (y
compris au niveau de la structure des programmes). L’envoi de message est le seul moyen qui
permet aux objets de communiquer entre eux. Smalltalk-76 introduit une relation d’héritage
entre classes. Smalltalk-80 est de typage dynamique, il introduit la notion de métaclasse
(classe dont les instances sont des classes).
— Flavors, Ceyx, Clos
Ces langages forment un mariage entre le langage de programmation Lisp et le paradigme
objet.
2
2.1
Objet
Trio <entité, attribut, valeur>
L’information peut être représentée par un ensemble de trios comme ¡voiture, couleur, rouge¿,
¡voiture, marque, Peugeot¿, etc. Les entités se caractérisent par un ensemble de propriétés.
L’attribut prend une valeur en fonction de sa nature.
Les objets seront définis et stockés en mémoire sous la forme d’ensemble attribut/valeur.
Le stockage des objets se fait en typant les attributs selon des types primitifs, ou en référence
à d’autres objets.
Rappelons que le référent est une variable informatique associée à un nom symbolique, codée
sur 34 bits et contenant l’adresse physique d’un objet informatique. Plusieurs référents distincts
peuvent désigner le même objet.
2.2
Envoi de message
Le seul mode de communication entre deux objets revient à appeler une méthode déclarée dans
un objet depuis un autre objet. Ceci s’appelle l’envoi de message.
Synchrone par défaut, mais on peut concevoir une programmation par envoir de messages
asynchrones
2.3
Objet composite
Les objets peuvent entrer dans une relation de type composition, où les uns se trouvent contenus
dans les autres et ne sont accessibles qu’à partir de ces autres.
Premier exemple : un objet manufacturé contient l’ensemble des pièces qui le composent.
La composition d’objet induit nécessairement que l’existence du composite dépende de l’existence du composant. En d’autres termes, la destruction du composite extraı̂nera la destruction du
composant.
5
Listing 1 – Composition voiture.cpp
#include <i o s t r e a m >
c l a s s Car b u r a t e u r
{
public :
Car bura t e u r ( ) {
s t d : : c e r r << ” C a r b u r a t e u r ” << t h i s << s t d : : e n d l ;
}
˜ Ca rbur a t e u r ( ) {
s t d : : c e r r << ” ˜ C a r b u r a t e u r ” << t h i s << s t d : : e n d l ;
}
void message ( ) {
s t d : : c e r r << ” Message c a r b u r a t e u r ” << t h i s << s t d : : e n d l ;
}
};
class Voiture
{
private :
Car bura t e u r carbu ;
public :
Voiture (){
s t d : : c e r r << ” V o i t u r e ” << t h i s << s t d : : e n d l ;
}
˜ Voiture (){
s t d : : c e r r << ” ˜ V o i t u r e ” << t h i s << s t d : : e n d l ;
}
void message ( ) {
s t d : : c e r r << ” Message v o i t u r e ” << t h i s << s t d : : e n d l ;
carbu . message ( ) ;
}
};
int
main ( int argn ,
char ∗∗ argv )
{
c l a s s V o i t u r e ∗ v o i t u r e = new V o i t u r e ( ) ;
v o i t u r e −>message ( ) ;
delete v o i t u r e ;
}
6
Listing 2 – Composition Carburateur.java
public c l a s s C a r b u r a t e u r {
Car bu r a t e u r ( ) {
System . out . p r i n t l n ( ” C a r b u r a t e u r ” ) ;
}
}
Listing 3 – Composition Voiture.java
public c l a s s V o i t u r e {
private C a r b u r a t e u r carbu ;
public V o i t u r e ( ) {
System . out . p r i n t l n ( ” V o i t u r e ” ) ;
carbu = new C a r b u r a t e u r ( ) ;
}
}
Listing 4 – Composition Main.java
public c l a s s Main {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
V o i t u r e v1 = new V o i t u r e ( ) ;
V o i t u r e v2 = new V o i t u r e ( ) ;
}
}
7
2.4
Objet agrégés ou associés
C’est une généralisation de la composition qui n’entraı̂ne pas l’appartenance.
Exemple : un produit manufacturé contient des types de pièces qui peuvent être répertoriées
dans un magasin de pièces de rechange. Ces types de pièces ne disparaissent pas avec la disparition
de l’objet manufacturé.
8
Listing 5 – Agrégation C++
#include <i o s t r e a m >
c l a s s Conducteur
{
public :
Conducteur ( ) {
s t d : : c e r r << ” Conducteur ” << t h i s << s t d : : e n d l ;
}
˜ Conducteur ( ) {
s t d : : c e r r << ” ˜ Conducteur ” << t h i s << s t d : : e n d l ;
}
void message ( ) {
s t d : : c e r r << ” Message c o n d u c t e u r ” << t h i s << s t d : : e n d l ;
}
};
class Voiture
{
private :
Conducteur ∗ c o n d u c t e u r ;
public :
V o i t u r e ( Conducteur ∗ c o n d u c t e u r ) {
this−>c o n d u c t e u r = c o n d u c t e u r ;
s t d : : c e r r << ” V o i t u r e ” << t h i s << s t d : : e n d l ;
}
˜ Voiture (){
s t d : : c e r r << ” ˜ V o i t u r e ” << t h i s << s t d : : e n d l ;
}
void message ( ) {
s t d : : c e r r << ” Message v o i t u r e ” << t h i s << s t d : : e n d l ;
conducteur −>message ( ) ;
}
};
int
main ( int argn ,
char ∗∗ argv )
{
c l a s s Conducteur ∗ c o n d u c t e u r = new Conducteur ( ) ;
c l a s s V o i t u r e ∗ v o i t u r e 1 = new V o i t u r e ( c o n d u c t e u r ) ;
c l a s s V o i t u r e ∗ v o i t u r e 2 = new V o i t u r e ( c o n d u c t e u r ) ;
v o i t u r e 1 −>message ( ) ;
v o i t u r e 2 −>message ( ) ;
delete v o i t u r e 1 ;
9
delete v o i t u r e 2 ;
}
10
Listing 6 – Agrégation Conducteur.java
c l a s s Conducteur {
Conducteur ( ) {
System . out . p r i n t f ( ” Conducteur \n” ) ;
}
}
Listing 7 – Agrégation Voiture.java
class Voiture {
private Conducteur c o n d u c t e u r ;
public V o i t u r e ( Conducteur c o n d u c t e u r ) {
System . out . p r i n t f ( ” V o i t u r e \n” ) ;
this . conducteur = conducteur ;
}
}
Listing 8 – Agrégation Main.java
public c l a s s Main {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
Conducteur c = new Conducteur ( ) ;
V o i t u r e v1 = new V o i t u r e ( c ) ;
V o i t u r e v2 = new V o i t u r e ( c ) ;
}
}
11
2.5
Objets dépendants
12
Listing 9 – Dépendance C++
#include <i o s t r e a m >
c l a s s Conducteur
{
public :
Conducteur ( ) {
s t d : : c e r r << ” Conducteur ” << t h i s << s t d : : e n d l ;
}
˜ Conducteur ( ) {
s t d : : c e r r << ” ˜ Conducteur ” << t h i s << s t d : : e n d l ;
}
void message ( ) {
s t d : : c e r r << ” message c o n d u c t e u r ” << t h i s << s t d : : e n d l ;
}
};
class Voiture
{
public :
Voiture (){
s t d : : c e r r << ” V o i t u r e ” << t h i s << s t d : : e n d l ;
}
˜ Voiture (){
s t d : : c e r r << ” ˜ V o i t u r e ” << t h i s << s t d : : e n d l ;
}
void message ( c l a s s Conducteur ∗ c o n d u c t e u r ) {
s t d : : c e r r << ” message v o i t u r e ” << t h i s << s t d : : e n d l ;
conducteur −>message ( ) ;
}
};
int
main ( int argn ,
char ∗∗ argv )
{
c l a s s Conducteur ∗ c o n d u c t e u r = new Conducteur ( ) ;
c l a s s V o i t u r e ∗ v o i t u r e = new V o i t u r e ( ) ;
v o i t u r e −>message ( c o n d u c t e u r ) ;
delete v o i t u r e ;
}
13
Listing 10 – Dépendance Conducteur.java
c l a s s Conducteur {
Conducteur ( ) {
System . out . p r i n t f ( ” Conducteur \n” ) ;
}
void message ( ) {
System . out . p r i n t l n ( ” Message ” + t h i s ) ;
}
}
Listing 11 – Dépendance Voiture.java
class Voiture {
public V o i t u r e ( ) {
System . out . p r i n t l n ( ” V o i t u r e ” ) ;
}
public void message ( Conducteur c o n d u c t e u r ) {
System . out . p r i n t l n ( ” Message ” + t h i s ) ;
c o n d u c t e u r . message ( ) ;
}
}
Listing 12 – Dépendance Main.java
public c l a s s Main {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
Conducteur c = new Conducteur ( ) ;
V o i t u r e v = new V o i t u r e ( ) ;
v . message ( c ) ;
}
}
— Agrégation forte = Agrégation par valeur = Composition
— Agrégation = Agrégation faible = Association
14
Voiture
Carburateur carb;
voitureProp
voitureMethod
Carburateur
carbuProp
carbuMethod
Association
Voiture
voitureProp
voitureMethod(Condu
cteur cond)
Conducteur
condProp
condMethod
Dépendance
Voiture
Carburateur carb
Conducteur cond
Composition
Carburateur
condProp
condMethod
Voiture(Carburateur carb){
this.cond = new Conducteur()
this.carb = carb;
}
Agrégation
Conducteur
condProp
condMethod
Figure 1 – Association – Dépendance
15
2.6
Encapsulation des attributs
Pourquoi les attributs d’un objet ne devraient-ils être accessible que par l’intermédiaure des
méthodes locales à ces objets ?
— Intégrité des classes :
Une classe et chargée de péserver l’intégrité des objets qu’elle définit.
— Gestion des exceptions
— Gestion des tests
— Cloisonnement des traitements, perennisation du code
— public : à tous ;
— protected : seulement aux objets de la classe elle-même et aux classes dérivées ;
— private : seulement par les objets de la classe elle-même ;
— package friendly par les objets de la classe elle-même et tout mon package
getters et setters
Règle générale. Si l’objet ne sert pas à partager des données :
— Attributs : private ou protected
— getters : public si l’on ne retourne pas de référence à des objets, sinon private ou protected
— setters : private ou protected
2.7
Encapsulation des méthodes
Les méthodes private sont responsables de l’implémentation de la classe, les méthodes public
sont responsables de l’implémentation de l’interface.
— public : Membres, Dérivés, Clients ;
— protected : Membres, Dérivés ;
— private : Membres.
— package friendly Membres, Clients du package.
2.8
2.8.1
Création et suppression d’objets
Ramasse-miettes (garbage collector )
16
Listing 13 – Garbage Collector Carburateur.java
c l a s s Car b u r a t e u r {
public C a r b u r a t e u r ( ) {
System . out . p r i n t l n ( t h i s ) ;
}
protected void f i n a l i z e ( ) {
System . out . p r i n t l n ( ” ˜ ” + t h i s ) ;
}
}
Listing 14 – Garbage Collector Voiture.java
class Voiture {
private C a r b u r a t e u r carbu ;
public V o i t u r e ( ) {
System . out . p r i n t l n ( t h i s ) ;
carbu = new C a r b u r a te u r ( ) ;
}
protected void f i n a l i z e ( ) {
System . out . p r i n t l n ( ” ˜ ” + t h i s ) ;
}
}
Listing 15 – Garbage Collector Main.java
public c l a s s Main {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
V o i t u r e v = new V o i t u r e ( ) ;
v = new V o i t u r e ( ) ;
v = null ;
System . gc ( ) ;
}
}
17
Listing 16 – Garbage Collector voiture.py
import gc
c l a s s Car b u r a t e u r :
def
init ( self ):
print ( ” C a r b u r a t e u r ” )
def
del ( self ):
print ( ” ˜ C a r b u r a t e u r ” )
class Voiture :
def
init ( self ):
print ( ” V o i t u r e ” )
s e l f . carbu = Carburateur ( )
def
del ( self ):
print ( ” ˜ V o i t u r e ” )
v1 = V o i t u r e ( )
v1 = V o i t u r e ( )
print ( ” coucou1 ” )
#v1 = None
#gc . c o l l e c t ( )
print ( ” coucou2 ” )
2.9
Cohésion et couplage
— Cohésion
— Traitements et Données forment un tout cohérent
— Préférer petits objets
— Couplage
— Minimiser communication entre objets
3
Classe
Une classe est un ensemble d’objets qui partagent les même types de propriétés et qui appliquent
les mêmes traitements à leurs données.
Attention : l’identité est toujours portée par l’objet.
— Nom
— Attributs
— Méthodes
3.1
Instanciation
Un objet est construit à partir d’une classe.
Où se trouve-t-il en mémoire ? Comment est-il accessible ?
18
Constructeur
Destructeur
this, self
3.2
Héritage
— Est une sous-classe
— Est une classe fille
— Est un — sous-ensemble
Relation : A hérite de B si les objets instance de A sont instances de B.
Du bon usage de l’héritage
—
—
—
—
Extension de classe
Adaptation du code
Factorisation du code
Extension de classe
On ajoute une méthode à une classe qui en étend une autre.
Exemple : Modification de la taille d’un ballon et de son élasticité (ballon gonflable).
— Adaptation du code
On redéfinit une méthode.
Exemple : Modification de la méthode conférant une force à une balle : Une balle de Jokari
aura une force inverse proportionnelle à l’élastique en plus de son poids.
Méthode : On appelle super et on complète.
— Factorisation du code
On étend une classe abstraite qui contient du code destiné à être réutilisé à différents endroits
du projet.
Exemple : Une balle contient l’implémentation de l’affichage d’un rond à l’écran. Selon le
type de balles, on aura d’autres affichages, mais celui-ci sera partagé pour toutes les balles.
Classe, Classe abstraite et Interface
Java
— Une classe implémente une ou plusieurs interfaces
— Une classe étend une seule classe
C++, PHP, Python
— C++ : Une classe implémente un ou plusieurs headers
— Une classe étend une ou plusieurs classes
19
Listing 17 – Héritage A.java
public c l a s s A {
public void message ( ) {
System . out . p r i n t l n ( ” message d ’ un o b j e t i n s t a n c e de A” ) ;
}
}
Listing 18 – Héritage B.java
public c l a s s B extends A{
public void message ( ) {
System . out . p r i n t l n ( ” message d ’ un o b j e t i n s t a n c e de B” ) ;
}
}
Listing 19 – Héritage Main.java
public c l a s s Main {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
A a = new A ( ) ;
B b = new B ( ) ;
a . message ( ) ;
a = b;
a . message ( ) ;
// b = a ; ERROR
b = (B) a ;
b . message ( ) ;
}
}
4
Types abstraits de données (ADT) et classes
—
—
—
—
Un ensemble d’instances T
Un ensemble d’opérations sur les éléments de T
Une encapsulation des propriétés et des opérations de T
Une responsabilité des opérations sur T
20
Exemple en C (de Hanson via Narbel) :
Listing 20 – stack.h
#i f n d e f STACK H
#define STACK H
typedef struct s t a c k ∗ s t a c k ;
int empty ( s t a c k ) ;
void p u s h f r o n t ( s t a c k , void ∗ ) ;
void push back ( s t a c k , void ∗ ) ;
void ∗ p o p f r o n t ( s t a c k ) ;
void ∗ pop back ( s t a c k ) ;
#endif // STACK H
Listing 21 – stack.cpp
#include ” s t a c k . h”
struct s t a c k {
int count ;
struct e l e m e n t {
void ∗x ;
struct e l e m e n t ∗ next ;
} ∗ head ;
};
s t a c k n e w s t a c k ( void ) {
s t a c k s t k = ( s t a c k ) m a l l o c ( s i z e o f ( struct s t a c k ) ) ;
stk −>count = 0 ;
stk −>head = NULL;
return s t k ;
}
int empty ( s t a c k s t k ) {
return stk −>count == 0 ;
}
void p u s h f r o n t ( s t a c k stk , void ∗x ) {
struct e l e m e n t e = ( s t a c k ) m a l l o c ( s i z e o f ( struct e l e m e n t ) ) ;
e−>x = x ;
e−>next = stk −>head ;
stk −>head = e ;
stk −>count++;
}
21
4.1
Modularité
Prenons le cas d’une pile implémentée sous la forme d’une liste chaı̂née et d’une pile implémentée
sous la forme d’un tableau.
La méthode push front n’est pas implémentée de la même manière. Pour autant, du point de
vue d’une ADT stack , c’est la même chose.
22
5
Polymorphisme
Polymorphisme
Implémentations différentes de la même interface pour un opérateur, une procédure ou une
fonction donnée.
Polymorphisme ad-hoc / overloading / surcharge
Définition différente des fonctions, procédures et opérateurs homonymes selon les types des
opérandes (exclu le type de self passé en paramètre en Python)
Exemples : surcharge d’opérateurs en C++, surcharge de constructeurs en Java, etc.
23
Exemple en C++
Listing 22 – generics-1.cc
#include <i o s t r e a m >
using namespace s t d ;
int calculerSomme ( int operande1 , int operande2 ) {
int r e s u l t a t = operande1 + operande2 ;
return r e s u l t a t ;
}
s t r i n g calculerSomme ( s t r i n g operande1 , s t r i n g operande2 ) {
s t r i n g r e s u l t a t = operande1 + operande2 ;
return r e s u l t a t ;
}
int myMax ( int o1 , int o2 ) {
return o1 > o2 ? o1 : o2 ;
}
s t r i n g myMax ( s t r i n g o1 , s t r i n g o2 ) {
return o1 > o2 ? o1 : o2 ;
}
int main ( ) {
int n1 = 4 , p1 = 1 2 ;
c o u t << n1 << ” + ” << p1 << ” = ” << calculerSomme ( n1 , p1 ) << e n d l ;
s t r i n g n2 = ” 4 ” , p2 = ” 12 ” ;
c o u t << n2 << ” + ” << p2 << ” = ” << calculerSomme ( n2 , p2 ) << e n d l ;
c o u t << ”Le max de ” << n1 << ” e t ” << p1 << ” e s t ” << myMax( n1 , p1 ) << e n d l ;
c o u t << ”Le max de ” << n2 << ” e t ” << p2 << ” e s t ” << max( n2 , p2 ) << e n d l ;
return 0 ;
}
Polymorphisme paramétrique / type variable / template / type générique
Même définition des fonctions, procédures et opérateurs homonymes avec un type variable
Exemples : Types variables en Ocaml, templates en C++ et Java
Polymorphisme d’héritage / overriding / redéfinition
Définition des méthodes par spécialisation. Quand les méthodes ont déjà été définies ou non
(interface en Java, méthode virtuelle pure en C++), je parle encore d’overriding, bien que cette
24
terminologie ne soit pas toujours employée.
Exemple : Implémentation d’une méthode d’une interface en Java, Redéfinition d’une méthode
héritée en Java, C++ ou Python.
25
Exemple en Java
Listing 23 – polymorphism-1/src/A.java
public c l a s s A {
public A( ) { } ;
public f i n a l void i d e n t i f y M y s e l f 1 ( ) {
System . out . p r i n t l n ( ” Je s u i s un A e t on ne r e v i e n t pas d e s s u s ” ) ;
}
public void i d e n t i f y M y s e l f 2 ( ) {
System . out . p r i n t l n ( ” Je s u i s un A s a u f c o n t r e −o r d r e ” ) ;
}
}
Listing 24 – polymorphism-1/src/B.java
public c l a s s B e x t e n d s A {
public B ( ) { } ;
public void i d e n t i f y M y s e l f 2 ( ) {
System . out . p r i n t l n ( ” Je s u i s un B” ) ;
}
}
Listing 25 – polymorphism-1/src/Main.java
public c l a s s Main {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
B b = new B ( ) ;
b. identifyMyself1 ( ) ;
b. identifyMyself2 ( ) ;
A a = new A ( ) ;
a = (A) b ;
a . identifyMyself1 ( ) ;
a . identifyMyself2 ( ) ;
}
}
26
Exemple en C++
Listing 26 – polymorphism-1.cc
#include <i o s t r e a m >
using namespace s t d ;
c l a s s A{
public :
void i d e n t i f y M y s e l f ( void ) {
c o u t << ” Je s u i s un A ” << e n d l ;
}
};
class B : A {
public :
void i d e n t i f y M y s e l f ( void ) {
c o u t << ” Je s u i s un B ” << e n d l ;
}
};
c l a s s C : A{
public :
void i d e n t i f y M y s e l f ( void ) {
c o u t << ” Je s u i s un C ” << e n d l ;
}
};
int main ( ) {
class A a ;
class B b ;
class C c ;
a . identifyMyself ();
b. identifyMyself ();
c . identifyMyself ();
return 0 ;
}
27
Exemple en C++
Listing 27 – polymorphism-2.cc
#include <i o s t r e a m >
using namespace s t d ;
c l a s s A{
public :
void i d e n t i f y M y s e l f 1 ( void ) {
c o u t << ” Je s u i s un A ” << e n d l ;
}
v i r t u a l void i d e n t i f y M y s e l f 2 ( void ) {
c o u t << ” Je s u i s un A s a u f c o n t r e o r d r e ” << e n d l ;
}
};
c l a s s B : public A {
public :
void i d e n t i f y M y s e l f 1 ( void
c o u t << ” Je s u i s un B ”
}
void i d e n t i f y M y s e l f 2 ( void
c o u t << ” Je s u i s un B ”
}
};
){
<< e n d l ;
){
<< e n d l ;
int main ( ) {
c o u t << ” c l a s s A a : ” << e n d l ;
class A a ;
a . identifyMyself1 ( ) ;
a . identifyMyself2 ( ) ;
c o u t << e n d l << ” c l a s s B b : ” << e n d l ;
class B b ;
b. identifyMyself1 ( ) ;
b. identifyMyself2 ( ) ;
c o u t << e n d l << ” c l a s s A &r a = b” << e n d l ;
c l a s s A &r a = b ;
ra . i d e n t i f y M y s e l f 1 ( ) ;
ra . i d e n t i f y M y s e l f 2 ( ) ;
return 0 ;
}
28
Classes génériques
Exemple en C++
Listing 28 – generics-1-bis.cc
#include <i o s t r e a m >
using namespace s t d ;
int ∗ c a l c u l e r S o m m e I n t ( int ∗ operande1 , int ∗ operande2 ) {
int ∗ r e s u l t a t = new int ( ∗ operande1 + ∗ operande2 ) ;
return r e s u l t a t ;
}
s t r i n g ∗ c a l c u l e r S o m m e S t r i n g ( s t r i n g ∗ operande1 , s t r i n g ∗ operande2 ) {
s t r i n g ∗ r e s u l t a t = new s t r i n g ( ∗ operande1 + ∗ operande2 ) ;
return r e s u l t a t ;
}
int main ( ) {
void ∗ ( ∗ calculerSomme ) ( void ∗ , void ∗ ) ;
int n1 = 4 , p1 = 1 2 ;
calculerSomme = ( void ∗ ( ∗ ) ( void ∗ , void ∗))& c a l c u l e r S o m m e I n t ;
c o u t << n1 << ” + ” << p1 << ” = ” << ∗ ( ( ( int ∗ ) ( calculerSomme (&n1 , &p1 ) ) ) ) << e n
s t r i n g n2 = ” 4 ” , p2 = ” 12 ” ;
calculerSomme = ( void ∗ ( ∗ ) ( void ∗ , void ∗))& c a l c u l e r S o m m e S t r i n g ;
c o u t << n2 << ” + ” << p2 << ” = ” << ∗ ( ( ( s t r i n g ∗ ) ( calculerSomme (&n2 , &p2 ) ) ) ) <<
return 0 ;
}
29
Exemple en C++
Listing 29 – generics-2.cc
#include <i o s t r e a m >
using namespace s t d ;
template<c l a s s T>
T calculerSomme (T operande1 , T operande2 )
{
T r e s u l t a t = operande1 + operande2 ;
return r e s u l t a t ;
}
template<typename T>
T myMax (T o1 , T o2 ) {
return o1 > o2 ? o1 : o2 ;
}
int main ( ) {
int n1 = 4 , p1 = 1 2 ;
c o u t << n1 << ” + ” << p1 << ” = ” << calculerSomme ( n1 , p1 ) << e n d l ;
s t r i n g n2 = ” 4 ” , p2 = ” 12 ” ;
c o u t << n2 << ” + ” << p2 << ” = ” << calculerSomme ( n2 , p2 ) << e n d l ;
c o u t << ”Le max de ” << n1 << ” e t ” << p1 << ” e s t ” << myMax( n1 , p1 ) << e n d l ;
c o u t << ”Le max de ” << n2 << ” e t ” << p2 << ” e s t ” << max( n2 , p2 ) << e n d l ;
return 0 ;
}
30
Exemple en C++
Listing 30 – generics-3.cc
#include <i o s t r e a m >
using namespace s t d ;
c l a s s A{
public :
s t r i n g t o S t r i n g ( ) { return ” Je s u i s un A ” ; }
};
c l a s s B{
public :
s t r i n g t o S t r i n g ( ) { return ” Je s u i s un B ” ; }
};
template<c l a s s T1 , c l a s s T2>
s t r i n g conc (T1 operande1 , T2 operande2 )
{
s t r i n g r e s u l t a t = operande1 . t o S t r i n g ( ) + operande2 . t o S t r i n g ( ) ;
return r e s u l t a t ;
}
int main ( ) {
class A a ;
class B b ;
c o u t << conc ( a , b ) << e n d l ;
return 0 ;
}
31
Exemple en C++
Listing 31 – generics-4.cc
#include <i o s t r e a m >
using namespace s t d ;
template <c l a s s T>
c l a s s Item {
public :
T element ;
Item<T> ∗ next ;
Item ( ) ;
˜ Item ( ) ;
};
template <c l a s s T>
Item<T> : : Item ( ) {
c o u t << ” Item ” << e n d l ;
}
template <c l a s s T>
Item<T> : : ˜ Item ( ) {
c o u t << ” ˜ Item ” << e n d l ;
}
template <c l a s s T>
class LinkedList {
private :
Item<T> ∗ head ;
public :
LinkedList ( ) ;
˜ LinkedList ( ) ;
T pop ( ) ;
void push (T ) ;
bool empty ( ) ;
void f l u s h ( ) ;
};
template <c l a s s T>
L i n k e d L i s t <T> : : L i n k e d L i s t ( ) {
c o u t << ” L i n k e d L i s t ” << e n d l ;
head = NULL;
32
}
template <c l a s s T>
L i n k e d L i s t <T> : : ˜ L i n k e d L i s t ( ) {
c o u t << ” ˜ L i n k e d L i s t ” << e n d l ;
}
template <c l a s s T>
void L i n k e d L i s t <T> : : push (T e l e m e n t )
{
Item<T> ∗tmp = new Item<T> ( ) ;
tmp−>e l e m e n t = e l e m e n t ;
tmp−>next = head ;
head = tmp ;
return ;
}
template <c l a s s T>
T L i n k e d L i s t <T> : : pop ( )
{
T tmp ;
Item<T> ∗ptmp = head ;
i f ( head != NULL) {
tmp = head−>e l e m e n t ;
head = head−>next ;
delete ptmp ;
}
return tmp ;
}
template <c l a s s T>
bool L i n k e d L i s t <T> : : empty ( )
{
return head == NULL;
}
template <c l a s s T>
void L i n k e d L i s t <T> : : f l u s h ( )
{
while ( head != NULL)
pop ( ) ;
}
int main ( ) {
33
L i n k e d L i s t <s t r i n g > l ;
l . push ( ”A” ) ;
l . push ( ”B” ) ;
l . push ( ”C” ) ;
c o u t << l . pop ( ) << e n d l ;
c o u t << l . pop ( ) << e n d l ;
l . flush ();
return 0 ;
}
34
Exemple en C++
Listing 32 – generics-5.cc
#include <i o s t r e a m >
using namespace s t d ;
c l a s s A{
public :
string toString ( ) ;
};
c l a s s B e x t e n d s A{
public :
s t r i n g t o S t r i n g ( ) { return ” Je s u i s un B ” ; }
};
c l a s s C e x t e n d s A{
public :
s t r i n g t o S t r i n g ( ) { return ” Je s u i s un C ” ; }
};
template<c l a s s T1 , c l a s s T2>
s t r i n g conc (T1 operande1 , T2 operande2 )
{
s t r i n g r e s u l t a t = operande1 . t o S t r i n g ( ) + operande2 . t o S t r i n g ( ) ;
return r e s u l t a t ;
}
int main ( ) {
class A a ;
class B b ;
class C c ;
c o u t << conc ( a , b ) << e n d l ;
return 0 ;
}
5.0.1
Héritage multiple
35
Listing 33 – Héritage multiple
class A {
public :
void f a ( ) { /∗ . . . ∗/ }
protected :
int x ;
};
class B {
public :
void f b ( ) { /∗ . . . ∗/ }
protected :
int x ;
};
c l a s s C: public B, public A {
public :
void f c ( ) ;
};
void C : : f c ( ) {
int i ;
fa ( ) ;
// i = x ; // ERROR
i = A : : x + B : : x ; // r e s o l u t i o n
}
int main ( ) {
}
6
Interface Homme-Machine
6.1
MVC
Présentation à l’écran d’un exemple complet d’implémentation Java d’HIM.
— Windows : JWindow, JFrame, JDialog
— Layout : BorderLayout, BoxLayout, CardLayout, FlowLayout, GridBagLayout, GridLayout,
GroupLayout, SpringLayout
— Container
JFrame ⇒ Content pane JFrame ⇒ Menu Bar frame.getContentPane().add(...)
— Widget
JButton, JTextfield, etc.
36
7
Design Patterns
7.1
Introduction
Rappelons les objectifs :
— Augmenter la modularité
— Augmenter la cohésion Exemple : MVC
— Abaisser la couplage
Deux principes fondamentaux :
— Préférer programmer des interfaces
Interfaces des objets :
Chaque objet déclare un ensemble d’opérations :
— Nom
— Objets qu’elle prend en paramètre
— Objet retourné
C’est précisément ce qui définit le type d’un objet.
Si l’interface d’un objet A contient l’interface d’un objet B, alors le type de B est un sous-type
de l’interface de B. Il y a héritage.
Il ne faut pas confondre héritage de classe et héritage d’interface :
— Héritage de classe : héritage des implémentations
— Héritage d’interfaces : sous-typage
37
Exemple Classe abstraite en C++ : Héritage d’interface
Listing 34 – signature.hh
#i f n d e f SIGNATURE H
#define SIGNATURE H
#include <s t r i n g >
using namespace s t d ;
class Signature {
private :
s t r i n g value ;
void e v a l S i g n a t u r e ( ) ;
public :
Signature ( ) ;
void s e t S i g n a t u r e V a l u e ( s t r i n g ) ;
s t r i n g getSignatureValue ( ) ;
string signature ( ) ;
void r e s e t S i g n a t u r e ( ) ;
v i r t u a l s t r i n g t o S t r i n g ( ) const =0;
};
#endif // SIGNATURE H
Listing 35 – arg.hh
#i f n d e f ARG H
#define ARG H
#include ” s i g n a t u r e . hh”
c l a s s Arg : public S i g n a t u r e {
private :
int data ;
public :
Arg ( ) ;
s t r i n g t o S t r i n g ( ) const ;
};
#endif // ARG H
Listing 36 – arg.cc
38
#include ” a r g . hh”
#include <sstream >
Arg : : Arg ( ) {
data =0;
}
s t r i n g Arg : : t o S t r i n g ( ) const {
std : : ostringstream oss ;
o s s << data ;
return o s s . s t r ( ) ;
}
S i g n a t u r e : : S i g n a t u r e ( ) { v a l u e=” ” ; }
s t r i n g S i g n a t u r e : : g e t S i g n a t u r e V a l u e ( ) { return v a l u e ; }
void S i g n a t u r e : : s e t S i g n a t u r e V a l u e ( s t r i n g v a l u e ) { this−>v a l u e=v a l u e ; }
s t r i n g S i g n a t u r e : : s i g n a t u r e ( ) { e v a l S i g n a t u r e ( ) ; return v a l u e ; }
void S i g n a t u r e : : e v a l S i g n a t u r e ( ) {
i f ( v a l u e == ” ” )
value = toString ( ) ;
}
void S i g n a t u r e : : r e s e t S i g n a t u r e ( ) {
v a l u e=” ” ;
evalSignature ( ) ;
}
int main ( int argn , char ∗∗ argv ) {
return 0 ;
}
39
Exemple héritage privé en C++ : Héritage de code
Listing 37 – array.hh
#i f n d e f ARRAY H
#define ARRAY H
c l a s s Array {
private :
int ∗ a r r a y ;
public :
Array ( ) ;
˜ Array ( ) ;
int p o p f r o n t ( ) ;
void p u s h f r o n t ( int ) ;
};
#endif // ARRAY H
Listing 38 – stackArray.hh
#i f n d e f STACKARRAY H
#define STACKARRAY H
#include ” a r r a y . hh”
c l a s s StackArray : private Array {
public :
StackArray ( ) ;
˜ StackArray ( ) ;
int pop ( ) ;
void push ( int ) ;
};
#endif // STACKARRAY H
Listing 39 – stackArray.cc
#include ” a r r a y . hh”
#include ” s t a c k A r r a y . hh”
#include <i o s t r e a m >
40
using namespace s t d ;
StackArray : : StackArray ( ) : Array ( ) {
c o u t << ” StackArray ” << e n d l ;
}
StackArray : : ˜ StackArray ( ) {
c o u t << ” ˜ StackArray ” << e n d l ;
}
int StackArray : : pop ( ) {
p o p f r o n t ( ) ; c o u t << ”pop” << e n d l ;
}
void StackArray : : push ( int k ) {
p u s h f r o n t ( k ) ; c o u t << ” push ” << k << e n d l ;
}
Array : : Array ( ) {
c o u t << ” Array ” << e n d l ;
}
Array : : ˜ Array ( ) {
c o u t << ” ˜ Array ” << e n d l ;
}
int Array : : p o p f r o n t ( ) {
c o u t << ” p o p f r o n t ” << e n d l ;
}
void Array : : p u s h f r o n t ( int k ) {
c o u t << ” p u s h f r o n t ” << k << e n d l ;
}
int main ( int argn , char ∗∗ argv ) {
StackArray s t a c k ;
s t a c k . push ( 1 ) ;
s t a c k . pop ( ) ;
// ERROR s t a c k . p u s h f r o n t ( 1 ) ;
return 0 ;
}
41
Pourquoi manipuler les objets par classes abtraites ?
Ceci procure au développeur des classes héritées un double avantage :
— Il peut ignorer les détails d’implémentation des classes, et ne savoir que les interfaces
— Il peut ignorer quel objet envoie le message
Exemple : Classe Signature
42
Exemple de composition en C++
Listing 40 – array.hh
#i f n d e f ARRAY H
#define ARRAY H
c l a s s Array {
private :
int ∗ a r r a y ;
public :
Array ( ) ;
˜ Array ( ) ;
int p o p f r o n t ( ) ;
void p u s h f r o n t ( int ) ;
};
#endif // ARRAY H
Listing 41 – stackArray.hh
#i f n d e f STACKARRAY H
#define STACKARRAY H
#include ” a r r a y . hh”
c l a s s StackArray {
private :
Array data ;
public :
StackArray ( ) ;
˜ StackArray ( ) ;
int pop ( ) ;
void push ( int ) ;
};
#endif // STACKARRAY H
Listing 42 – stackArray.cc
43
#include ” a r r a y . hh”
#include ” stackArray −2.hh”
#include <i o s t r e a m >
using namespace s t d ;
StackArray : : StackArray ( ) {
c o u t << ” StackArray ” << e n d l ;
}
StackArray : : ˜ StackArray ( ) {
c o u t << ” ˜ StackArray ” << e n d l ;
}
int StackArray : : pop ( ) {
data . p o p f r o n t ( ) ; c o u t << ”pop” << e n d l ;
}
void StackArray : : push ( int k ) {
data . p u s h f r o n t ( k ) ; c o u t << ” push ” << k << e n d l ;
}
Array : : Array ( ) {
c o u t << ” Array ” << e n d l ;
}
Array : : ˜ Array ( ) {
c o u t << ” ˜ Array ” << e n d l ;
}
int Array : : p o p f r o n t ( ) {
c o u t << ” p o p f r o n t ” << e n d l ;
}
void Array : : p u s h f r o n t ( int k ) {
c o u t << ” p u s h f r o n t ” << k << e n d l ;
}
int main ( int argn , char ∗∗ argv ) {
StackArray s t a c k ;
s t a c k . push ( 1 ) ;
s t a c k . pop ( ) ;
// s t a c k . d a t a . p u s h f r o n t ( 2 ) ; ERROR: p r i v a t e !
return 0 ;
}
44
— Préférer la composition à l’héritage
Deux techniques pour faire réutiliser des fonctionnalités :
1. Héritage de classe
2. Composition d’objets
— Spécificités
1. Héritage de classe Boı̂te blanche : le contenu des classes parentes est visible depuis
les classes héritées.
Définition statique à la compilation.
Possibilité de surcharger des opérations.
2. Composition d’objets Boı̂te noire : le contenu de l’objet est accessible depuis son
interface.
Définie dynamiquement lors de création de références à d’autres objets.
— Avantages
1. Héritage de classe
Facilité de compléter un composant pour en créer un nouveau.
2. Composition d’objets
Conserve l’encapsulation de chaque classe.
— Inconvénients
1. Héritage de classe
Pas possible de modifier le code hérité.
Rompt l’encapsulation : modification de classe parente impose modification des classes
héritées.
2. Composition d’objets
Coût en nombre d’objets... perte d’efficacité à l’exécution.
45
7.2
Singleton
Listing 43 – Singleton
public c l a s s Main {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
Uniq i n s t a n c e = Uniq . i n s t a n c e ( 5 ) ;
i n s t a n c e . message ( ) ;
i n s t a n c e = Uniq . i n s t a n c e ( 6 ) ;
i n s t a n c e . message ( ) ;
}
}
public c l a s s Uniq {
private s t a t i c Uniq i n s t a n c e ;
private int data ;
private Uniq ( int data ) {
t h i s . data=data ;
}
public s t a t i c Uniq i n s t a n c e ( int data ) {
i f ( i n s t a n c e==null )
i n s t a n c e = new Uniq ( data ) ;
return i n s t a n c e ;
}
public void message ( ) {
System . out . p r i n t l n ( data ) ;
}
}
46
7.3
Abstract Factory
Listing 44 – Abstract Factory
public abstract c l a s s A b s t r a c t F a c t o r y {
abstract Shape c r e a t e S q u a r e ( ) ;
abstract Shape c r e a t e R e c t a n g l e ( ) ;
}
public c l a s s C o l o r e d R e c t a n g l e implements Shape {
@Override
public void message ( ) {
System . out . p r i n t l n ( ” I am a C o l o r e d R e c t a n g l e ” ) ;
}
}
public c l a s s C ol or e dS ha pe F ac to ry extends ShapeFactory {
@Override
Shape c r e a t e R e c t a n g l e ( ) {
return new C o l o r e d R e c t a n g l e ( ) ;
}
}
public c l a s s Main {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
ShapeFactory s h a p e F a c t o r y = new ShapeFactory ( ) ;
ShapeFactory c o l o r e d S h a p e F a c t o r y = new C ol or e dS ha pe F ac to ry ( ) ;
Shape s 1 = s h a p e F a c t o r y . c r e a t e S q u a r e ( ) ;
Shape s 2 = s h a p e F a c t o r y . c r e a t e R e c t a n g l e ( ) ;
Shape s 3 = c o l o r e d S h a p e F a c t o r y . c r e a t e R e c t a n g l e ( ) ;
s 1 . message ( ) ;
s 2 . message ( ) ;
s 3 . message ( ) ;
}
}
public c l a s s R e c t a n g l e implements Shape {
@Override
public void message ( ) {
47
System . out . p r i n t l n ( ” I am a R e c t a n g l e ” ) ;
}
}
public c l a s s ShapeFactory extends A b s t r a c t F a c t o r y {
@Override
Shape c r e a t e S q u a r e ( ) {
return new Square ( ) ;
}
@Override
Shape c r e a t e R e c t a n g l e ( ) {
return new R e c t a n g l e ( ) ;
}
}
public i n t e r f a c e Shape {
public void message ( ) ;
}
public c l a s s Square implements Shape {
@Override
public void message ( ) {
System . out . p r i n t l n ( ” I am a Square ” ) ;
}
}
48
7.4
Adapter
Listing 45 – Adapter
public c l a s s C o l o r e d R e c t a n g l e {
void drawWithColor ( ) {
// draw a c o l o r e d r e c t a n g l e
}
}
public c l a s s R e c t a n g l e implements Shape {
private C o l o r e d R e c t a n g l e c r ;
public R e c t a n g l e ( ) {
c r = new C o l o r e d R e c t a n g l e ( ) ;
}
@Override
public void draw ( ) {
c r . drawWithColor ( ) ;
}
}
public i n t e r f a c e Shape {
public void draw ( ) ;
}
49
7.5
Template method
Listing 46 – Template Method
public abstract c l a s s A {
void method ( ) {
primitive method ( ) ;
}
abstract void p r i m i t i v e m e t h o d ( ) ;
}
public c l a s s B extends A {
@Override
void p r i m i t i v e m e t h o d ( ) {
}
}
50
7.6
State
Listing 47 – State
#include <i o s t r e a m >
using namespace s t d ;
class IState
{
public :
v i r t u a l void h a n d l e ( c l a s s Context ∗ m)=0;
};
c l a s s Context
{
private :
class IState ∗ state ;
public :
Context ( ) ;
void s e t S t a t e ( I S t a t e ∗ s ) {
state = s ;
}
void r e q u e s t ( ) {
s t a t e −>h a n d l e ( t h i s ) ;
}
};
c l a s s ON: public I S t a t e
{
public :
void h a n d l e ( Context ∗ ) ;
};
c l a s s OFF: public I S t a t e
{
public :
void h a n d l e ( Context ∗ ) ;
};
void ON : : h a n d l e ( Context ∗ c )
{
c o u t << ”on” << e n d l ;
c−>s e t S t a t e (new OFF ( ) ) ;
delete t h i s ;
51
}
void OFF : : h a n d l e ( Context ∗ c )
{
c o u t << ” o f f ” << e n d l ;
c−>s e t S t a t e (new ON( ) ) ;
delete t h i s ;
}
Context : : Context ( )
{
s t a t e = new OFF ( ) ;
}
int main ( )
{
Context c o n t e x t ;
context . request ( ) ;
context . request ( ) ;
context . request ( ) ;
context . request ( ) ;
}
52
7.7
Observer
Listing 48 – Observer
#include <s t r i n g >
#include < l i s t >
#include <i o s t r e a m >
using namespace s t d ;
class IObserver {
public :
v i r t u a l void n o t i f y ( int ) = 0 ;
};
class IObservable {
public :
v i r t u a l void n o t i f y O b s e r v e r s ( ) = 0 ;
v i r t u a l void addObserver ( c l a s s Observer ∗ ) = 0 ;
v i r t u a l void removeObserver ( c l a s s Observer ∗ ) = 0 ;
};
c l a s s Observer : public I O b s e r v e r {
private :
int s t a t e ;
public :
void n o t i f y ( int s t a t e ) {
c o u t << ” r e c e i p t from ” << t h i s << ” : ” << s t a t e << e n d l ;
}
};
c l a s s O b s e r v a b l e : public I O b s e r v a b l e {
private :
l i s t <Observer∗> o b s e r v e r s ;
int s t a t e ;
public :
Observable ( ) {
state = 0;
}
void s e t S t a t e ( int s t a t e ) {
this−>s t a t e = s t a t e ;
}
53
void n o t i f y O b s e r v e r s ( ) {
for ( l i s t <c l a s s Observer ∗ >:: c o n s t i t e r a t o r i t = o b s e r v e r s . b e g i n ( ) ; i t != o b s e r v
( ∗ i t )−> n o t i f y ( s t a t e ) ;
}
void addObserver ( Observer ∗ o b s e r v e r ) {
observers . push front ( observer ) ;
}
void removeObserver ( Observer ∗ o b s e r v e r ) {
o b s e r v e r s . remove ( o b s e r v e r ) ;
}
};
c l a s s O b s e r v a b l e 1 : public O b s e r v a b l e {
public :
void run ( ) {
while ( true ) {
int i n p u t ;
c i n >> i n p u t ;
setState ( input ) ;
notifyObservers ( ) ;
}
}
};
int main ( ) {
Observer o b s e r v e r 1 , o b s e r v e r 2 , o b s e r v e r 3 , o b s e r v e r 4 , o b s e r v e r 5 , o b s e r v e r 6 ;
Observable1 observable1 ;
o b s e r v a b l e 1 . addObserver(& o b s e r v e r 1 ) ;
o b s e r v a b l e 1 . addObserver(& o b s e r v e r 2 ) ;
o b s e r v a b l e 1 . addObserver(& o b s e r v e r 3 ) ;
o b s e r v a b l e 1 . addObserver(& o b s e r v e r 4 ) ;
o b s e r v a b l e 1 . addObserver(& o b s e r v e r 5 ) ;
o b s e r v a b l e 1 . addObserver(& o b s e r v e r 6 ) ;
o b s e r v a b l e 1 . run ( ) ;
return 0 ;
}
54
Listing 49 – Observer
package f r . ubordeaux . oa ;
import j a v a . awt . e v e n t . ActionEvent ;
import j a v a . awt . e v e n t . A c t i o n L i s t e n e r ;
public c l a s s C o n t r o l l e r implements A c t i o n L i s t e n e r {
Model model ;
View view ;
public C o n t r o l l e r ( Model model , View view ) {
t h i s . model=model ;
t h i s . view=view ;
view . getButton ( ) . a d d A c t i o n L i s t e n e r ( t h i s ) ;
f o r ( J L a b e l O b s e r v e r i : view . g e t T a r g e t L a b e l s ( ) )
model . addObserver ( i ) ;
}
@Override
public void a c t i o n P e r f o r m e d ( ActionEvent a r g 0 ) {
model . s e t S o u r c e ( I n t e g e r . p a r s e I n t ( view . g e t T e x t f i e l d ( ) . getText ( ) ) ) ;
model . c a l c u l a t e ( ) ;
}
}
package f r . ubordeaux . oa ;
import j a v a . u t i l . O b s e r v a b l e ;
import j a v a . u t i l . Observer ;
import j a v a x . swing . JLabel ;
public c l a s s J L a b e l O b s e r v e r extends JLabel implements Observer {
private int i n d e x ;
public J L a b e l O b s e r v e r ( int i n d e x ) {
super ( ) ;
t h i s . i n d e x=i n d e x ;
}
@Override
public void update ( O b s e r v a b l e o b s e r v a b l e , Object o b j e c t ) {
55
Model model = ( Model ) o b s e r v a b l e ;
t h i s . s e t T e x t ( S t r i n g . v a l u e O f ( model . g e t T a r g e t s ( ) [ i n d e x ] ) ) ;
}
}
package f r . ubordeaux . oa ;
public c l a s s Main {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
Model model = new Model ( ) ;
View view = new View ( ) ;
new C o n t r o l l e r ( model , view ) ;
}
}
package f r . ubordeaux . oa ;
import j a v a . u t i l . O b s e r v a b l e ;
public c l a s s Model extends O b s e r v a b l e {
private int s o u r c e ;
private int t a r g e t s [ ] ;
public Model ( ) {
t a r g e t s = new int [ 1 0 ] ;
}
public void s e t S o u r c e ( int s o u r c e ) {
this . source = source ;
}
public void c a l c u l a t e ( ) {
f o r ( int i =0; i <=9; i ++)
t a r g e t s [ i ] = s o u r c e ∗ ( i +1);
t h i s . setChanged ( ) ;
this . notifyObservers ( ) ;
}
public int [ ] g e t T a r g e t s ( ) {
return t a r g e t s ;
}
56
}
package f r . ubordeaux . oa ;
import j a v a . awt . GridLayout ;
import j a v a . u t i l . O b s e r v a b l e ;
import j a v a . u t i l . Observer ;
import
import
import
import
import
j a v a x . swing . JButton ;
j a v a x . swing . JFrame ;
j a v a x . swing . JLabel ;
j a v a x . swing . JPanel ;
j a v a x . swing . J T e x t F i e l d ;
public c l a s s View {
private
private
private
private
private
private
JFrame frame ;
JPanel p a n e l ;
JTextField t e x t f i e l d ;
JLabel s o u r c e L a b e l s [ ] ;
JLabelObserver t a r g e t L a b e l s [ ] ;
JButton button ;
public View ( ) {
frame = new JFrame ( ” C o n v e r t i s s e u r ” ) ;
// frame . s e t S i z e ( 5 0 0 0 , 1 0 0 ) ;
p a n e l = new JPanel ( ) ;
frame . add ( p a n e l ) ;
GridLayout l a y o u t = new GridLayout ( ) ;
l a y o u t . setColumns ( 1 2 ) ;
l a y o u t . setRows ( 2 ) ;
panel . setLayout ( layout ) ;
t e x t f i e l d = new J T e x t F i e l d ( 6 ) ;
s o u r c e L a b e l s = new JLabel [ 1 0 ] ;
t a r g e t L a b e l s = new J L a b e l O b s e r v e r [ 1 0 ] ;
f o r ( int i =0; i <=9; i ++){
s o u r c e L a b e l s [ i ] = new JLabel ( S t r i n g . v a l u e O f ( i + 1 ) ) ;
t a r g e t L a b e l s [ i ] = new J L a b e l O b s e r v e r ( i ) ;
}
button = new JButton ( ”=” ) ;
p a n e l . add ( t e x t f i e l d ) ;
p a n e l . add ( button ) ;
f o r ( JLabel l a b e l : s o u r c e L a b e l s )
p a n e l . add ( l a b e l ) ;
p a n e l . add (new JLabel ( ) ) ;
57
p a n e l . add (new JLabel ( ) ) ;
f o r ( JLabel l a b e l : t a r g e t L a b e l s )
p a n e l . add ( l a b e l ) ;
frame . pack ( ) ;
frame . s e t V i s i b l e ( true ) ;
frame . s e t D e f a u l t C l o s e O p e r a t i o n ( JFrame . EXIT ON CLOSE ) ;
}
public J T e x t F i e l d g e t T e x t f i e l d ( ) {
return t e x t f i e l d ;
}
public JButton getButton ( ) {
return button ;
}
public J L a b e l O b s e r v e r [ ] g e t T a r g e t L a b e l s ( ) {
return t a r g e t L a b e l s ;
}
}
8
Exceptions
Une exception est une condition exceptionnelle pendant l’exécution d’un programme. Par exemple,
l’accès à une zone de mémoire inaccessible, l’accès à un indice inexistant d’un tableau, l’écriture
dans un fichier protégé, l’envoi d’un signal par le système d’exploitation ou une division par zéro.
La gestion des exceptions dans un langage de programmation impératif consiste à séparer
l’exécution normale du programme de l’exécution exceptionnelle. Le but est d’éviter un plantage
du processus et sa continuation vers l’affichage d’un message d’erreur ou encore la réparation avant
poursuite.
8.1
Exceptions en Java
Java propose une implémentation de la gestion des exceptions sans reprise ni réparation. Il s’agit
simplement de détourner le code par l’intermédiaire de l’instruction try/catch/finally.
Une exception est un objet de type java.lang.Throwable. Leurs sous-classes sont Error et
Exception.
On déclare une exception dans la signature d’une méthode : throws
public s t a t i c S t r i n g r e a d F i l e ( S t r i n g f i l e n a m e ) throws IOException {
...
}
58
L’instruction try/catch/finally
L’instruction try contient le code à exécuter controlé par un ensemble de blocs d’exception
catch. Enfin, le bloc facultatif finally est exécuté quoi qu’il arrive.
L’instruction throw prend en argument un objet dont le type est Throwable. Elle saisie l’exception
public c l a s s Main {
public s t a t i c void main ( S t r i n g [ ] a r g s ) throws Throwable {
try {
System . out . p r i n t l n ( ” Begin ” ) ;
throw new Throwable ( ) ;
// System . o u t . p r i n t l n (” Continue ” ) ;
} catch ( Throwable e ) {
System . out . p r i n t l n ( ” E x c e p t i o n ” ) ;
System . out . p r i n t l n ( e . t o S t r i n g ( ) ) ;
System . out . p r i n t l n ( ”End e x c e p t i o n ” ) ;
} finally {
System . out . p r i n t l n ( ”End” ) ;
}
}
}
59
Listing 50 – Exception 1
package e1 ;
public c l a s s Main {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
// TODO Auto−g e n e r a t e d method s t u b
int i , j , k ;
i =1;
j =0;
try {
k=i / j ;
} catch ( A r i t h m e t i c E x c e p t i o n e ) {
e . printStackTrace ( ) ;
System . out . p r i n t l n ( e . t o S t r i n g ( ) ) ;
} finally {
System . out . p r i n t l n ( ” ok ” ) ;
}
}
}
60
Listing 51 – Exception 2
package e2 ;
public c l a s s MyException extends E x c e p t i o n {
public MyException ( ) {
super ( ) ;
// TODO Auto−g e n e r a t e d c o n s t r u c t o r s t u b
}
public MyException ( S t r i n g message , Throwable cause , boolean e n a b l e S u p p r e s s i
super ( message , cause , e n a b l e S u p p r e s s i o n , w r i t a b l e S t a c k T r a c e ) ;
// TODO Auto−g e n e r a t e d c o n s t r u c t o r s t u b
}
public MyException ( S t r i n g message , Throwable c a u s e ) {
super ( message , c a u s e ) ;
// TODO Auto−g e n e r a t e d c o n s t r u c t o r s t u b
}
public MyException ( S t r i n g message ) {
super ( message ) ;
System . e r r . p r i n t l n ( ”ERROR: ” + message ) ;
// TODO Auto−g e n e r a t e d c o n s t r u c t o r s t u b
}
public MyException ( Throwable c a u s e ) {
super ( c a u s e ) ;
// TODO Auto−g e n e r a t e d c o n s t r u c t o r s t u b
}
}
61
Listing 52 – Exception 2
package e2 ;
public c l a s s Main {
public s t a t i c void main ( S t r i n g [ ] a r g s ) throws MyException {
try {
throw new MyException ( ” c e c i e s t l e message ” ) ;
}
catch ( MyException e ) {
}
}
}
62
Listing 53 – Exception 3
public c l a s s MyException extends E x c e p t i o n {
public MyException ( S t r i n g s t r i n g , E x c e p t i o n e ) {
System . e r r . p r i n t l n ( ” Message : ” + s t r i n g ) ;
System . e r r . p r i n t l n ( ” Cause : ” + e . getMessage ( ) ) ;
}
}
Listing 54 – Exception 3 (suite)
import j a v a . i o . F i l e ;
import j a v a . i o . F i l e R e a d e r ;
import j a v a . i o . IOException ;
public c l a s s Main {
public s t a t i c void main ( S t r i n g [ ] a r g s ) throws MyException {
S t r i n g data = r e a d F i l e ( ) ;
System . out . p r i n t l n ( data ) ;
}
private s t a t i c S t r i n g r e a d F i l e ( ) throws MyException {
// F i l e f i l e = new F i l e (” d o e s n o t e x i s t ” ) ;
F i l e f i l e = new F i l e ( ” u n r e a d a b l e ” ) ;
F i l e R e a d e r r e a d e r = null ;
S t r i n g B u f f e r data = new S t r i n g B u f f e r ( ) ;
char [ ] c b u f = new char [ 1 0 2 4 ] ;
try {
r e a d e r = new F i l e R e a d e r ( f i l e ) ;
int l e n g h t = 0 ;
while ( ( l e n g h t=r e a d e r . r e a d ( c b u f ) ) > 0 )
data . append ( cbuf , 0 , l e n g h t ) ;
} catch ( IOException e ) {
throw new MyException ( ” E r r e u r l e c t u r e ” , e ) ;
} finally {
try {
i f ( r e a d e r != null )
reader . close ( ) ;
} catch ( IOException e ) {
e . printStackTrace ( ) ;
63
}
}
return data . t o S t r i n g ( ) ;
}
}
9
Clonage
64
Listing 55 – Clone
public c l a s s A implements C l o n e a b l e {
public int a t t r ;
public B l i n k ;
public A( int a t t r , B l i n k ) {
t h i s . a t t r=a t t r ;
t h i s . l i n k=l i n k ;
}
public boolean e q u a l s ( Object o ) {
i f ( t h i s==o )
return true ;
else {
i f ( o instanceof A) {
i f ( ( a t t r == ( (A) o ) . a t t r ) &&
( l i n k . e q u a l s ( ( (A) o ) . l i n k ) ) )
return true ;
else
return f a l s e ;
}
}
return f a l s e ;
}
public Object c l o n e ( ) throws CloneNotSupportedException {
A newA = (A) super . c l o n e ( ) ;
newA . l i n k = (B) l i n k . c l o n e ( ) ;
return newA ;
}
}
Listing 56 – Clone
public c l a s s B implements C l o n e a b l e {
public int a t t r ;
public B( int a t t r ) {
65
this . a t t r = a t t r ;
}
public boolean e q u a l s ( Object o ) {
i f ( t h i s==o )
return true ;
else {
i f ( o instanceof B) {
i f ( a t t r == ( (B) o ) . a t t r )
return true ;
else
return f a l s e ;
}
}
return f a l s e ;
}
public Object c l o n e ( ) throws CloneNotSupportedException {
return super . c l o n e ( ) ;
}
}
Listing 57 – Clone
public c l a s s Main {
public s t a t i c void main ( S t r i n g [ ] a r g s ) {
B b = new B ( 5 ) ;
B o t h e r b = new B ( 5 ) ;
B auxb = new B ( 1 0 ) ;
auxb = b ;
A a = new A( 1 0 , b ) ;
A o t h e r a = new A( 1 0 , o t h e r b ) ;
A auxa = null ;
try {
auxa = (A) o t h e r a . c l o n e ( ) ;
} catch ( CloneNotSupportedException e ) {
e . printStackTrace ( ) ;
}
i f ( b == o t h e r b )
66
System . out . p r i n t l n ( ”b = o t h e r b ” ) ;
i f (b . equals ( otherb ))
System . out . p r i n t l n ( ”b e q u a l s o t h e r b ” ) ;
i f ( b == auxb )
System . out . p r i n t l n ( ”b = auxb ” ) ;
i f ( b . e q u a l s ( auxb ) )
System . out . p r i n t l n ( ”b e q u a l s auxb ” ) ;
i f ( a == o t h e r a )
System . out . p r i n t l n ( ” a = o t h e r a ” ) ;
i f ( a . equals ( othera ))
System . out . p r i n t l n ( ” a e q u a l s o t h e r a ” ) ;
i f ( a == auxa )
System . out . p r i n t l n ( ” a = auxa ” ) ;
i f ( a . e q u a l s ( auxa ) )
System . out . p r i n t l n ( ” a e q u a l s auxa ” ) ;
}
}
b
b
b
a
a
equals
= auxb
equals
equals
equals
otherb
auxb
othera
auxa
67

Documents pareils