• Aucun résultat trouvé

Architecture INTERFACE et Design Pattern JAVA

N/A
N/A
Protected

Academic year: 2022

Partager "Architecture INTERFACE et Design Pattern JAVA"

Copied!
21
0
0

Texte intégral

(1)

JAVA – Interface - page 1/21 - Bertrand LIAUDET

Architecture

INTERFACE et Design Pattern JAVA SOMMAIRE

SOMMAIRE 1

INTERFACE 2

Interface – présentation générale 2

Présentation 2

Syntaxe 5

Interface et polymorphisme – Principe de substitution 8

Distinction avec les classes abstraites 10

Interface – 3 exemples d’usages possibles 11

1 - Découplage entre classe client et classe modèle : interface proposée et interface

utilisée 11

2 - Interface et héritage multiple de spécifications (ou d’usages) 14

3 - Avoir des méthodes « variables » 16

Exercices 21

Tester les codes 21

Compléter les codes 21

Version avril 2019

(2)

JAVA – Interface - page 2/21 - Bertrand LIAUDET

INTERFACE

Interface – présentation générale

Présentation Polysémie

Le terme interface a couramment plusieurs sens distincts :

• Dans un sens général, c’est la partie située entre deux éléments matériels ou logiciels qui permet l’échange d’informations. Par exemple, l’IHM (interface homme-machine), c’est l’écran, le clavier, la souris, etc. L’IHM permet l’échange d’informations entre l’homme et la machine (le logiciel).

• Au sens de la POO, d’un point de vue fonctionnel, l’interface d’une classe est la partie publique (public ou de niveau paquetage) de la classe, que ce soit ses méthodes ou ses attributs. En général, il s’agit donc d’une liste de méthodes permettant d’utiliser la classe et de la considérer comme une « boite noire ».

• Au sens de la POO, d’un point de vue technique, une interface c’est aussi un ensemble de méthodes abstraites (donc d’en-têtes de méthodes) qui seront à réaliser (à coder) par les classes qui implémenteront l’interface. C’est aussi un ensemble de constantes. Cela conduit à l’utilisation d’un nouveau mot-clé : « interface ».

• En programmation, la notion d’API, Application Programming Interface, designe un ensemble de bibliothèques, de fonctions, de classes et/ou d’objets utilisables dans le code.

Les bibliothèques Java sont des API (avec toutes leurs classes). Le DOM JavaScript est une API (avec son objet « document »).

• En programmation WEB, la notion d’API web désigne un ensemble de services ou de fichiers qu’un site WEB met à disposition pour le développement d’un autre site WEB.

Toutes ces significations se rejoignent. Il faut essayer d’en comprendre le principe.

(3)

JAVA – Interface - page 3/21 - Bertrand LIAUDET

Présentation technique de P.O.O.

• Une interface est une classe abstraite qui n’a pas d’attributs autres que des constantes de classe et qui n’a que des méthodes abstraites : c’est donc un cas particulier de classe abstraite.

• Une interface ne peut pas être instanciée, mais on peut déclarer des objets de type interface.

• La relation entre une classe et une interface n’est plus une relation d’héritage mais une relation d’implémentation : une classe implémente (ou implante ou réalise) une interface. Une classe qui implémente une interface doit coder les méthodes de l’interface.

Toutefois, une classe abstraite peut implémenter une interface avec des méthodes abstraites qui seront donc finalement implémentées par les méthodes des classes réalisant la classe abstraite.

• Il faut distinguer entre implémenter une méthode (forcément abstraite) et redéfinir une méthode (override) forcément concrète, et surcharger une méthode (overload) forcément concrète aussi.

Une classe peut implémenter plusieurs interfaces tandis qu’elle ne peut hériter que d’une seule classe de base, qu’elle soit abstraite ou pas.

• Une interface peut hériter d’une autre interface.

• Une interface est soit « public », soit du niveau de son paquetage.

• Les constantes sont forcément « public static final » et rien d’autre.

• Les méthodes sont forcément « public abstract » et rien d’autre.

(4)

JAVA – Interface - page 4/21 - Bertrand LIAUDET

Présentation fonctionnelle : interface proposée et interface utilisée Ø Fonctionnalités proposées

Une interface peut être vue comme étant un ensemble de fonctionnalités proposées par une classe, fonctionnalités qui pourront être ensuite utilisées par une autre classe.

En tant que fonctionnalités proposées, l’interface est un contrat qui impose aux classes qui l’implémentent de coder les en-têtes que l’interface définit.

Ø Fonctionnalités à utiliser

En tant que fonctionnalités à utiliser, une interface définit un protocole d’utilisation (comme n’importe quelle classe qu’on utilise) pour les classes qui vont l’utiliser.

Une classe qui utilise une interface instanciera un objet d’une classe qui réalise cette interface.

Ø Formalisme UML :

La flèche de réalisation d’interface est la même que celle de l’héritage mais le trait est en pointillé.

La flèche de dépendance (trait en pointillé, pointe en V) est une flèche qui dit que la classe source (« ClasseQuiUtilise ») utilise un objet de la classe cible (IClasseQuiPropose).

<<réalise>>

<<use>>

ClasseQuiUtilise IClasseQuiPropose ClasseQuiRealise

(5)

JAVA – Interface - page 5/21 - Bertrand LIAUDET

Syntaxe Déclaration

public interface I { int MAX = 1000;

void methode1();

int methode2 (String ch, MaClasse maClasse);

}

Une interface se déclare comme une classe mais :

• Une interface peut être « public » ou de niveau paquetage (pas de modificateur).

• On utilise le mot-clé « interface » à la place de « class » pour définir une interface.

• Les méthodes d’une interface sont des méthodes abstraites : elles n’ont pas de corps mais que leurs signatures (donc pas de bloc ouvert et fermé par des accolades).

• Les méthodes d’une interface sont forcément « public abstract » : ces modificateurs sont donc facultatifs.

• Les constantes sont forcément « public static final » : ces modificateurs sont donc facultatifs.

Ø Commentaires

Etant donné qu’une interface est un contrat de réalisation de méthodes dont la signature est fixée et dont l’usage peut être associé à des constantes elles-mêmes fournies par l’interface, il est prudent de préciser clairement en commentaire ce qu’on attend des méthodes à réaliser, et de préciser clairement la signification des constantes.

(6)

JAVA – Interface - page 6/21 - Bertrand LIAUDET

Implémentation - Réalisation

Ø Une classe implémente (ou réalise) une interface class A implement I {

void methode1(){

// implementation de methode1 ;

// utilisation possible de MAX directement }

int methode2 (String ch, MaClasse maClasse, etc…){

// implementation de methode2

// utilisation possible de MAX directement }

}

On peut utiliser MAX directement (sans le préfixer par le nom de l’interface).

Comme toute constante de classe, MAX est aussi utilisable par une classe qui n’implémente pas l’interface en préfixant son nom par celui de l’interface : « I.MAX ».

(7)

JAVA – Interface - page 7/21 - Bertrand LIAUDET

Subtilités

Ø Dérivation d’interface

Une interface peut dériver (hériter) d’une ou plusieurs autres interfaces : ce qui veut dire que pour la réaliser, il faudra aussi réaliser toutes les méthodes des interfaces dont elle dérive.

public interface I extends I1, I2, I3 { … ]

Déclarer I dérivant de I1, I2 et I3 c’est exactement la même chose que de déclarer I en y ajoutant toutes les méthodes et tous les attributs de I1, I2 et I3.

Ø Une classe peut implémenter plusieurs interfaces class A implement I1, I2, I3 {

}

A noter que dans le cas d’une implémentation multiple, si les interfaces proposent plusieurs fois la méme méthode avec la même signature, alors il suffira de réaliser la méthode une fois.

Deux interfaces proposant deux méthodes avec les mêmes paramètres mais un type de retour différent seront nécessairement incompatibles car les deux méthodes ne pourront pas être implémentées en même temps.

Ø Une classe peut dériver d’une autre classe et implémenter plusieurs interfaces class A extends B implement I1, I2, I3 {

}

Ø Objet interface et méthode

Une méthode peut retourner une interface et peut aussi avoir une interface en paramètre. C’est la même chose avec une classe abstraite.

Bien sûr, les objets effectivement passés en paramètre à la méthode ou renvoyés par la méthode seront des objets de classe réalisant l’interface ou la classe abstraite.

(8)

JAVA – Interface - page 8/21 - Bertrand LIAUDET

Interface et polymorphisme – Principe de substitution Objet « interface » et polymorphisme : règle de substitution

On peut déclarer un objet de type Interface.

Bien sûr, on ne peut pas instancier un objet de type Interface.

Par contre, puisque tout objet d’une classe de base est substituable par un objet d’une de ses classes dérivées (principe de substitution), on peut affecter à un objet interface une instance d’une classe qui réalise l’interface.

IC i ;

i = new C();

Avec un objet de l’interface IC, on pourra manipuler tous les objets des classes qui implémentent IC.

(9)

JAVA – Interface - page 9/21 - Bertrand LIAUDET

Code correspondant au formalisme UML :

<<réalise>>

<<use>>

Main Classe

+ <<Implement>> m1 () IClasse

+ m1 ()

public interface IClasse { void m1();

}

public class Classe implement IClasse { ...

}

public class Main { ...

IClasse obj ;

obj = new Classe(...) ; obj.m1() ;

...

}

(10)

JAVA – Interface - page 10/21 - Bertrand LIAUDET

Distinction avec les classes abstraites

L’interface est un cas particulier de classe abstraite

Une interface est un cas particulier de classe abstraite (classe abstraite qui n’a pas d’attributs autres que des constantes et qui n’a que des méthodes abstraites).

Les interfaces ont le même fonctionnement polymorphe que les classes abstraites.

Ø Exemple :

On peut reprendre l’exemple donnée pour les classes abstraites, exemple pour lequel la classe abstraite n’a pas de méthodes réalisées et pas d’attribut, et on peut remplacer la classe abstraite par une interface et obtenir le même fonctionnement polymorphe.

Distinction entre interface et classe abstraite

Dans le cas d’un héritage, on s’intéresse à la relation « est-un » qui est une relation

« ontologique » c’est-à-dire qu’elle concerne surtout les attributs communs.

Dans le cas d’une interface, on s’intéresse à la relation « sait faire » qui est une relation

« fonctionnelle ». Il ne s’agit plus de dériver d’un autre objet mais de savoir faire un certain nombre de choses. On s’intéresse surtout aux méthodes.

(11)

JAVA – Interface - page 11/21 - Bertrand LIAUDET

Interface – 3 exemples d’usages possibles

1 - Découplage entre classe client et classe modèle : interface proposée et interface utilisée Principe

La notion d’interface permet d’accentuer encore un peu plus l’encapsulation en définissant les méthodes utiles à l’utilisation d’une classe ou d’un paquetage dans une classe interface.

Ainsi l’utilisateur pourra directement déclarer un objet de type interface, puis instancier un objet réalisant l’interface.

Modèle UML général

<<réalise>>

<<use>>

ClasseQuiUtilise IClasseQuiPropose ClasseQuiRealise

ou

<<réalise>>

ClasseQuiUtilise IClasseQuiPropose ClasseQuiRealise

La composition signifie que la ClasseQuiUtilise contient un attribut de classe IClasseQuiPropose.

(12)

JAVA – Interface - page 12/21 - Bertrand LIAUDET

Exemple de découplage de l’interface utilisateur

<<réalise>>

Ecran ICalcul Calcul

+ +

m1 () m2 ()

public Ecran(){

ICalcul calcul;

Ecran(ICalcul calcul){ this.calcul = calcul;}

...

void test(){

...

calcul.m1() ; ...

} }

Ø Remarques

• calcul est un attribut de la classe Ecran

• Le découplage fait que la méthode test() fonctionne pour tout objet réalisant ICalcul. Avec le constructeur, seule l’instantiation d’un Ecran est dépendante du Calcul :

Ecran e=new Ecran(new Calcul()) ;

(13)

JAVA – Interface - page 13/21 - Bertrand LIAUDET

Exemple : le design pattern Adapter

Le pattern adapter permet d’ajouter une nouvelle classe ou un nouveau composant à un modèle en faisant en sorte que l’interface du modèle ne change pas et donc que le client puisse continuer à fonctionner identiquement.

L’adaptateur se branche sur l’interface du modèle en intégrant la nouvelle classe ou le nouveau composant.

Le pattern Adapter est utile quand on veut intégrer un composant existant déjà et dont l’interface n’est pas standard par rapport au client de notre modèle.

Modèle de départ

NouvelleClasse est une classe à adapter au modèle et à sont interface

Classe ajoutée pour permettre l'adaptation au

modèle de l'élément à adapter

<<realize>>

<<realize>>

nouvelleClasseAdaptee

<<use>>

Adapter

- nouvelleClasseAdaptee : NouvelleClasse = new NouvelleClasse() + <<Implement>> operation (int nombre1, int nombre2) : void

InterfaceStandard

+ operation (int pNombre1, int pNombre2) : void

ClasseDuModele

+ <<Implement>> operation (int nombre1, int nombre2) : void MainClient

+ main (String args[]) : void

NouvelleClasse

+ +

operation1 (int nombre1, int nombre2) operation2 (int nombre)

: int : void

(14)

JAVA – Interface - page 14/21 - Bertrand LIAUDET

2 - Interface et héritage multiple de spécifications (ou d’usages) Le problème de l’héritage multiple

L’héritage multiple n’est pas pris en compte en Java.

La difficulté de l’héritage multiple vient du fait que les méthodes peuvent apparaître à plusieurs niveaux du réseau d’héritage qui n’est plus une simple branche d’arbre.

En cas d’ajout d’un héritage multiple sur un système fonctionnant déjà, on risque donc d’utiliser une méthode à la place d’une autre tandis qu’on ne le souhaitait pas.

La solution de l’interface

Une interface permet de gérer de l’héritage multiple en le limitant au niveau de la signature des méthodes (l’en-tête) et non pas du corps des méthodes. Cela supprime tous les risques de conflit au niveau des méthodes puisqu’une méthode ne pourra finalement être réalisée qu’une seule fois.

D’un point de vue méthodologique, dans un héritage multiple, il faut définir l’héritage principal (ou la filiation) à partir des attributs puis considérer tous les autres comme des interfaces, c’est- à-dire comme des héritages qui se limiteront à des méthodes abstraites.

D’un point de vue pratique, l’héritage multiple via des interfaces oblige tout de même à implémenter le code des méthodes. La généralisation se limite à l’en-tête. Son intérêt est donc surtout de normaliser l’interface pour les utilisateurs.

(15)

JAVA – Interface - page 15/21 - Bertrand LIAUDET

Exemple

<<réalise>>

<<réalise>>

<<réalise>>

Etudiant

ISalarié

+ +

UsageSalarié 1 () UsageSalarié 2 () Personne

{abstract}

- - -

nom adresse tél

: String : String : String + afficherCoordonnées ()

Salarié IEtudiant

+ +

UsageEtudiant 1 () UsageEtudiant 2 ()

Dans ce cas, Etudiant et Salarié héritent de Personne : ils ont un nom, une adresse et un tél qu’on peut afficher.

Par ailleurs le Salarié réalise les usages imposés dans ISalarié et l’Etudiant ceux imposés par IEtudiant.

On considère que l’étudiant « est un » salarié. L’Etudiant ne peut pas hériter du Salarié puisqu’il hérite déjà de la classe personne. Par contre, il va réaliser l’interface ISalarié, héritant ainsi en quelque sorte des Usages du salarié. Les spécifications sont imposées par l’interface mais il faudra tout de même recoder les méthodes déjà codées dans Salarié.

(16)

JAVA – Interface - page 16/21 - Bertrand LIAUDET

3 - Avoir des méthodes « variables » Héritage vs. Délégation

La délégation offre un mécanisme de réutilisation aussi puissant que celui offert par la généralisation.

L’héritage est une construction rigide mais la propagation des attributs et des méthodes est automatique. L’héritage correspond à une relation « est-un » stricte, c’est-à-dire pas à une relation « a-un-comportement-de ».

La délégation est une construction plus souple basée sur l’agrégation. La propagation des propriétés doit être réalisée manuellement. Elle permet généralement la mise en œuvre de généralisation multiple.

(17)

JAVA – Interface - page 17/21 - Bertrand LIAUDET

Ø Héritage

dormir : chanterBerceuse();

dormir :

if getAge() <10 raconterHistoire();

Personne[] tab=new Personne[4];

tab[0]=new Bebe("Lawrence", 1);

tab[1]=new Enfant("Berenice",9);

tab[2]=new Enfant("Aurelien",5);

tab[3]=new Personne("Bertrand",49);

for(int i=0; i<tab.length; i++) tab[i].dormir();

<<use>>

Bebe

+ + +

<<Constructor>>

<<Override>>

Bebe (String nom, int age) dormir ()

chanterBerceuse ()

: void : void Personne

- -

nom age

: String : int +

+ + +

<<Constructor>> Personne (String nom, int age) getNom ()

getAge () dormir ()

: String : int : void

Enfant

+ + +

<<Constructor>>

<<Override>>

Enfant (String nom, int age) dormir ()

raconterHistoire ()

: void : void Main

+ main (String args[]) : void

Ici le mécanisme est un mécanisme classique d’héritage et de polymorphisme.

(18)

JAVA – Interface - page 18/21 - Bertrand LIAUDET

Ø Délégation – polymorphisme par délégation

Personne[] tab=new Personne[4];

tab[0]=new Personne("Lawrence", 1, new Bebe());

tab[1]=new Personne("Berenice",9, new Enfant());

tab[2]=new Personne("Aurelien",5, new Enfant());

tab[3]=new Personne("Bertrand",49,new Sommeil());

for(int i=0; i<tab.length; i++) tab[i].dormir();

<<use>>

dormir (p) : chanterBerceuse();

dormir (p) :

if p.getAge() <10 raconterHistoire();

dormir : s.dormir(this);

s

Bebe

+ +

<<Override>> dormir (Personne p) chanterBerceuse ()

: void : void

Sommeil

+ dormir (Personne p) : void

Enfant

+ +

<<Override>> dormir (Personne p) raconterHistoire ()

: void : void Main

+ main (String args[]) : void

Personne -

- -

nom age s

: String : int : Sommeil +

+ + +

<<Constructor>> Personne (String nom, int age, Sommeil s) getNom ()

getAge () dormir ()

: String : int : void

Ici on obtient le polymorphisme par la délégation.

On fournit l’objet « p » à la méthode dormir pour accéder aux méthodes de Personne, si nécessaire (ici : if p.getAge <10…).

On peut considérer qu’on « sette » une méthode spécifique à la personne au moment de son instanciation : « new Personne("Lawrence", 1, new Bebe()); » consiste à setter la méthode

« dormir » des Bébé à la personne, comme on lui a setté son prénom et son âge.

Cette technique sera particulièrement utile en cas d’héritage multiple car cette fois-ci elle offrira une solution plus performante que la solution de l’héritage classique. On verra ça particulièrement dans le design pattern Stratégie.

(19)

JAVA – Interface - page 19/21 - Bertrand LIAUDET

Exemple : le pattern Strategy (délégation)

http://rpouiller.developpez.com/tutoriel/java/design-patterns-gang-of-four/?page=page_4#LVI-I

Ø Description du pattern (objectif, définition)

• Encapsule des comportements d’une même famille (des méthodes) et utilise la délégation pour savoir lequel utiliser.

• « sette » des méthodes à travers une interface : permet ainsi d’avoir une méthode

« variable ».

• Adapter le comportement d’un objet en fonction d’un besoin sans changer les interactions, et donc indépendamment du client.

• Définir une famille d'algorithmes interchangeables et permettre de les changer indépendamment de la partie cliente.

Ø Principes de résolution

Quand un objet Entité est instancié par un objet Client, il est instancié avec une stratégie concrète (un objet de Strategie1 ou un objet de Strategie2). De ce fait, la méthode calcul de l’objet Entité (qui exécute strategie.calcul() ) réagit différement selon la stratégie concrète instancié.

Ainsi, les objets de la classe Entité accèdent de façon polymorphe aux méthodes de la classe

« Stratégie »

La classe Stratégie est une interface qui définit les comportements.

Les stratégies concrètes réalisent cette interface.

(20)

JAVA – Interface - page 20/21 - Bertrand LIAUDET

UML

1

# strategie Entité

+ calcul ()

Strategie 1 + <<Implement>> calcul () Strategie

+ calcul () Client

+ main (String args[]) : void

Strategie 2 + <<Implement>> calcul ()

(21)

JAVA – Interface - page 21/21 - Bertrand LIAUDET

Exercices

Tester les codes

Chargez les codes « Archi-5-1-Interface-code-POO.zip »

Pour tester l’exemple et faire les exercices, il faut un JDK : les commandes javac et java doivent être reconnues dans une console.

L’objectif est surtout de tester les exemples 50, 51 et 52.

Chaque dossier contient un lisez-moi.

Une fois les exemples installés et testés, il faut regarder le code pour le comprendre.

Compléter les codes Exemples 50

Ajoutez le cas d’un adolescent : l’âge sera compris entre 16 et 20 ans. La méthode de sommeil sera : consulter les réseaux sociaux.

Exemples 51

Ajouter un moteur télécommandé au système et créer un 2ème leurre dans le main, d’abord

« normal », puis en lui donnant un moteur télécommandé.

Références

Documents relatifs

• On peut ordonner les threads en utilisant des méthodes explicites pour endormir le thread courant, ou abandonner son exécution au profit d'un autre (sleep et

Remarque: une classe abstraite peut posséder des méthodes concrètes ou abstraites; si une classe possède une méthode abstraite, toutes les classes dérivées devront implémenter

By means of quasi-2D experiments and 2D numerical tests we investigate the particle flow around a moving intruder immersed into an ensiled granular material.. The intruder (a blade)

with 4F2hc] Na + indep.: cationic amino acids; Na + depen.: large neutral l -amino acids (system y + L) E (preferentially intracellular cationic amino acid for extracellular

Une classe qui implémente une (ou plusieurs) interface(s) sans redéfinir toutes les méthodes abstraites est également abstraite et doit être déclarée telle avec le

Also matching is the user:Mailbox:Inbox and user:Mailbox:Local Folder – all three of these element sets are therefore potentially amenable for display using the

Une classe dérivée d’une classe non abstraite peut être déclarée abstraite et/ou contenir des méthodes abstraites... Java Classes et

La fenêtre joue le rôle de « conteneur » dans lequel vont être disposés les différents éléments constitutifs (composants) de l’interface. graphique de l’application