1. Présentation sur
Le pattern Adaptateur
Presenté par Khaled Amirat
Supervisé par Mr Mezred Youcef
Département de mathématiques et d'informatique
Université de Souk Ahras, Algérie
2017
1
2. Design Patterns de structure (1)
Abstraction de la manière dont les classes et les objets sont
composés pour former des structures plus importantes.
Deux types de motifs
– Motifs de structure de classes .
– Motifs de structure d’objets .
3. Design Patterns de structure (2)
– Motifs de structure de classes
• Utilisation de l’héritage pour composer des interfaces et/ou des
implémentations (ex : Adapter).
– Motifs de structure d’objets
• composition d’objets pour réaliser de nouvelles fonctionnalités :
4. Adaptateur (patron de conception)
En génie logiciel, adaptateur (ou wrapper) est un patron de
conception (design pattern) de type structure (structural). Il permet de
convertir l'interface d'une classe en une autre interface que le client
attend.
L’adaptateur fait fonctionner ensemble des classes qui n'auraient
pas pu fonctionner sans lui, à cause d'une incompatibilité d'interfaces.
5. Applicabilité (1)
Il permet d'intégrer une classe à ne pas modifier, par exemple :
● Une API tiers convient au besoin fonctionnel, mais la signature
de ses méthodes ne convient pas.
● L'utilisation d'anciennes classes doit être normalisée, sans pour
autant en reprendre tout le code.
6. Applicabilité (2)
Un objet adaptateur sert de liaison entre les objets manipulés et un
programme les utilisant, permettant la communication entre classes.
Il est utilisé pour convertir l'interface d'un objet vers une autre
interface, attendue par le client pour utiliser l'objet en question.
7. Structure
Une cible ( IAdaptateur ) définit l’interface spécifique à
l’application app ca o que le e client c e utilise .
Le Client collabore avec les objets qui sont conformes à l’interface
de IAdaptateur .
L classe l à adapter d t ( Adapté é ) est t l’interface l’i t f existante i t t
qui i a besoin d’adaptation .
L’adaptateur p ( Adaptateur p ) adapte p effectivement l’interface
de Adapté à l’interface de IAdaptateur par traduction des accès
9. Example (1)
Une société souhaite produire un chargeur universel de batteries pour téléphone portable pouvant délivrer jusqu'à
10 volts en sortie. Les ingénieurs ont produit un premier prototype de chargeur:
public class Chargeur
{
// le portable branché sur le chargeur
private IChargeable telephone;
// le voltage en sortie du chargeur
private const int voltage = 10;
// branchement d'un portable pour le charger
public void brancherPortable(IChargeable portable)
{
System.out.println("branchement d'un portable");
this.telephone = portable;
this.telephone.Recharger(voltage);
}
}
10. Example (2)
Celui-ci est capable de se brancher sur tout téléphone implémentant l'interface
IChargeable via la méthode brancherPortable et de le recharger en produisant 10 volts en
sortie.
public interface IChargeable
{
/*
méthode appelée si l'on veut recharger le portable
*/
/* @param name="volts" voltage en sortie du chargeur */
void Recharger(int volts);
}
11. Example (3)
Celui-ci est capable de se brancher sur tout téléphone implémentant l'interface
IChargeable via la méthode brancherPortable et de le recharger en produisant 10 volts en
sortie.
public interface IChargeable{
/* méthode appelée si l'on veut recharger le portable
/* @param name="volts" voltage en sortie du chargeur */
void Recharger(int volts);
}
12. Example (4)
On créé plusieurs téléphones portables de test qui implémentant l'interface IChargeable
dont Comme suit:
public class PortableDeTest Implements IChargeable
{
public void Recharger(int volts)
{
System.out.println( "Portable de test en charge" );
System.out.println( "voltage: {0}" , volts);
}
}
13. Example (5)
Les tests effectués en laboratoire sont concluants. Le chargeur fonctionne à la perfection
avec tous les téléphones implémentant l'interface IChargeable.
Cependant les problèmes apparaissent lors de tests avec les téléphones portables
actuellement sur le marché (par exemple avec la marque Oppo ou encore Condor ). En effet,
chaque fabriquant de téléphone propose son propre système de chargement. Les interfaces
sont non seulement différentes mais le voltage utilisé varie aussi d'un téléphone à l'autre
(allant de 10 à 5 volts). Le chargeur universel ne l'est alors plus du tout. Il devient donc
impossible d'utiliser Ce chargeur avec les téléphones existants. Malheur, la faillite sonne à la
porte de la société!
14. Example (6)
Proposition des solution
"Nous avons besoin que les téléphones implémentent l'interface IChargeable mais nous
ne pouvons pas les modifier nous même. Nous n'en possédons pas le code source. Il nous
suffit donc de proposer notre interface IChargeable aux différents constructeurs et de leur
demander de l'implémenter dans leur téléphone."
15. Example (7)
Prenons un exemple courant
"les prises électriques. Si vous voyagez en Angleterre par exemple et tentez de brancher
une fiche électrique française sur la prise murale anglaise vous risquez d'avoir quelques
problèmes, les interfaces n'étant pas compatibles. Alors que faites vous ? Vous descendez au
magasin de bricolage du quartier pour acheter un adaptateur. Un coté de l'adaptateur s'adapte
à l'interface de la prise murale anglaise tandis que l'autre s'adapte à la fiche française. Au
milieu s'opèrent des transformations afin que les deux cotés puissent communiquer."
16. Example (8)
Back Again ! Proposition des solution
Opposition "Les constructeurs ont leur propre système et n'ont pas l'intention de le
changer. Tu imagines s'ils devaient prendre en compte les demandes des centaines de
constructeurs de chargeurs et autres périphériques, ils ne s'en sortiraient pas. Et puis que
faire des téléphones déjà vendus ?
Ils n'implémenteraient pas IChargeable et ne pourraient donc pas être utilisés par notre
chargeur !" "Ce n'est donc pas au fabriquant du portable à modifier son code mais à nous de
nous y adapter. Adapter, voilà un mot intéressant. Ce qu'il nous faudrait c'est en fait quelque
chose qui puisse adapter le code des téléphones pour que notre chargeur puisse l'utiliser, un
adaptateur en somme."
17. Example (9)
Proposition des solution
Donc !! "Nous allons créer un adaptateur pour chaque portable que l'on voudra utiliser
avec notre chargeur. Nous aurons donc un chargeur unique dont le code ne changera pas
auquel nous pourrons brancher n'importe quel téléphone en utilisant le bon adaptateur."
18. Example (10)
Occupons nous d'abord du côté s'interfaçant avec le chargeur. Ce dernier ne manipule
que des objets de type IChargeable.
L'adaptateur va devoir implémenter l'interface IChargeable afin que le chargeur puisse
l'utiliser.
Pour le coté s'adaptant au portable, l'adaptateur devra posséder une référence sur le
portable qu'il est censé adapter.
C'est en effet l'adaptateur qui manipulera directement l'instance du portable et non pas le
chargeur.
19. Example (11)
public class PortableOppo{
// ne se recharge qu'avec du 10 volts
public void ChargerBatteries(int volts)
{
System.out.println("Portable SonneEricSonne en charge");
System.out.println("voltage: {0}", volts);
}
}
public class PortableCondor{
// ne se recharge qu'avec du 5 volts
public void ChargerPortable(int volts)
{
System.out.println("Portable SamSaoule en charge");
System.out.println("voltage: {0}", volts);
}
}
Étudions deux exemples de téléphones portables: SonneEricSonne et SamSaoule. Voici
les classes les représentants:
20. Example (12)
Nous allons donc construire un adaptateur pour chaque téléphone. Voici tout d'abord
l'adaptateur pour téléphones SonneEricSonne:
AdaptateurOppo
Class
PortableOppo
Class
telephone : PortableOppo
AdaptateurOppo()
Recharger() : void
PortableOppo
21. Example (13)
public class AdaptateurOppo Implements IChargeable{
// référence sur le portable adapté
private PortableSonneEricSonne telephone ;
public AdaptateurOppo( PortableOppo portable)
{
this.telephone = portable;
}
public void Recharger(int volts)
{
this.telephone.ChargerBatteries( volts);
}
}
22. Example (14)
L'adaptateur implémente l'interface IChargeable afin de pouvoir être manipulé par le
chargeur.
Nous utilisons le constructeur de l'adaptateur afin de lui donner une référence sur le
téléphone qu'il est censé adapter.
Nous gardons cette référence via un champ privé. Il ne reste plus qu'à saisir le code de la
méthode Recharger.
Le chargeur appelle cette méthode en passant en paramètre le voltage.
L'adaptateur se charge d'envoyer cet appel au téléphone dont il s'occupe (lui seul sait
comment manipuler un téléphone Oppo).
Passons maintenant à l'adaptateur pour téléphones Condor.
23. Example (15)
AdaptateurCondor
Class
PortableCondor
Class
telephone : PortableCondor
AdaptateurCondor()
Recharger() : void
PortableCondor
public class AdaptateurCondor Implements IChargeable{
// référence sur le portable adapté
private PortableCondor telephone;
public AdaptateurCondor(PortableCondor portable){
this.telephone = portable;
}
//le portable SamSaoule n'a besoin que de 5 volts
public void Recharger(int volts){
//on modifie le voltage
int nouveauVoltage = volts > 5 ? 5 : volts ;
this.telephone.ChargerPortable(nouveauVoltage);
}
}
24. Example (16)
Rien d'extraordinaire par rapport à l'adaptateur précédent. La nouveauté se situe au
niveau de la méthode Recharger. Ici l'adaptateur ne se contente pas simplement de traduire
les appels du chargeur vers le portable. Vous vous souvenez sans doute que les portables
Condor n'ont besoin que de 5 volts. Et bien c'est l'adaptateur qui va se charger d'effectuer la
transformation. L'adaptateur encapsule toutes les différences entre le chargeur et le portable.
Le chargeur n'a donc aucun lien avec le portable, seul l'adaptateur connait les spécificités de ce
dernier. D'ailleurs, si vous réfléchissez, vous verrez qu'en fait le chargeur ne sait même pas
que c'est un téléphone portable qu'il est en train de charger. La société a bien compris. Elle
s'est donc empressée de créer des adaptateurs pour toute sorte d'appareils (piles
rechargeables, balladeurs MP3, etc.) tout en gardant le même chargeur de départ. Maintenant
que les adaptateurs sont créés, il ne reste plus qu'à les tester. Voici donc un petit programme
en mode console:
25. Example (17)
static void Main(string[] args){
//on crée le chargeur
Chargeur chargeur = new Chargeur();
/******************** Portable Oppo***********************/
//on crée le portable et son adaptateur
PortableOppo portableOp = new PortableOppo();
AdaptateurOppo adapateurOp = new AdaptateurOppo( portableOp);
//on donne le portable à charger mais en utilisant son adaptateur
chargeur.brancherPortable( adapateurOp);
System.out.println( );
/********************* Portable Condor***************************/
//on crée le portable et son adaptateur
PortableCondor portableCo = new PortableSamSaoule( );
AdaptateurCondor adapateurCo = new AdaptateurCondor( portableCon);
//on donne le portable à charger mais en utilisant son adaptateur
chargeur.brancherPortable( adapateurCon);
}
26. Example (18)
Execution :
branchement d’un portable
portableOppo on charge
voltage : 10
branchement d’un portable
portableCondor on charge
voltage : 6
Comme vous le voyez, les adaptateurs ont parfaitement fonctionné. Nous avons pu
recharger des téléphones de marques différentes grâce aux adaptateurs. De plus,
l'adaptateur pour téléphone SamSaoule a bien adapté le voltage en le ramenant à 5.
27. Conséquences
Pour la classe de l’objet qui adapte
Pas possible d’adapter une classe et ses sous sous-classes classes .
Mais redéfinition possible du comportement (sous-classe) .
Pour l’objet qui adapte
Un Adaptateur peut travailler avec plusieurs Adaptées .
Plus difficile de redéfinir le comportement d d’Adaptée Adaptée (sous- (sous
classer puis obliger Adaptateur à référencer la sous-classe) .
28. Conclusion
Ici s'achève notre découverte du pattern Adaptateur. A partir
de maintenant lorsque vous devrez utiliser une classe existante
et que son interface ne correspond pas à celle que vous attendez,
vous saurez quoi faire.