pont

V-B. Pont (Bridge ou Handle/Body)

OBJECTIFS :

  • Découpler l'abstraction d'un concept de son implémentation.
  • Permettre à l'abstraction et l'implémentation de varier indépendamment.
RAISONS DE L'UTILISER :

Le système comporte une couche bas niveau réalisant l'implémentation et une couche haut niveau réalisant l'abstraction. Il est nécessaire que chaque couche soit indépendante.

Cela peut être le cas du système d'édition de documents d'une application. Pour l'implémentation, il est possible que l'édition aboutisse à une sortie imprimante, une image sur disque, un document PDF, etc... Pour l'abstraction, il est possible qu'il s'agisse d'édition de factures, de rapports de stock, de courriers divers, etc...

Chaque implémentation présente une interface pour les opérations de bas niveau standard (sortie imprimante), et chaque abstraction hérite d'une classe effectuant le lien avec cette interface (tracer une ligne). Ainsi les abstractions peuvent utiliser ce lien pour appeler la couche implémentation pour leurs besoins (imprimer facture).

RESULTAT :

Le Design Pattern permet d'isoler le lien entre une couche de haut niveau et celle de bas niveau.

RESPONSABILITES :

  • Implementation : définit l'interface de l'implémentation. Cette interface n'a pas besoin de correspondre à l'interface de l'Abstraction. L'Implementation peut, par exemple, définir des opérations primitives de bas niveau et l'Abstraction des opérations de haut niveau qui utilisent les opérations de l'Implementation.
  • ImplementationA et ImplementationB : sont des sous-classes concrètes de l'implémentation.
  • Abstraction : définit l'interface de l'abstraction. Elle possède une référence vers un objet Implementation. C'est elle qui définit le lien entre l'abstraction et l'implémentation. Pour définir ce lien, la classe implémente des méthodes qui appellent des méthodes de l'objet Implementation.
  • AbstractionA et AbstractionB : sont des sous-classes concrètes de l'abstraction. Elle utilise les méthodes définies par la classe Abstraction.
  • La partie cliente fournit un objet Implementation à l'objet Abstraction. Puis, elle fait appel aux méthodes fournit par l'interface de l'abstraction.
IMPLEMENTATION JAVA :
Implementation.java
/**
* Définit l'interface de l'implémentation.
* L'implémentation fournit deux méthodes
*/
public interface Implementation {

public void operationImpl1(String pMessage);
public void operationImpl2(Integer pNombre);
}
ImplementationA.java
/**
* Sous-classe concrète de l'implémentation
*/
public class ImplementationA implements Implementation {

public void operationImpl1(String pMessage) {
System.out.println("operationImpl1 de ImplementationA : " + pMessage);
}

public void operationImpl2(Integer pNombre) {
System.out.println("operationImpl2 de ImplementationA : " + pNombre);
}
}
ImplementationB.java
/**
* Sous-classe concrète de l'implémentation
*/
public class ImplementationB implements Implementation {

public void operationImpl1(String pMessage) {
System.out.println("operationImpl1 de ImplementationB : " + pMessage);
}

public void operationImpl2(Integer pNombre) {
System.out.println("operationImpl2 de ImplementationB : " + pNombre);
}
}
Abstraction.java
/**
* Définit l'interface de l'abstraction
*/
public abstract class Abstraction {

// Référence vers l'implémentation
private Implementation implementation;

protected Abstraction(Implementation pImplementation) {
implementation = pImplementation;
}

public abstract void operation();

/**
* Lien vers la méthode operationImpl1() de l'implémentation
* @param pMessage
*/
protected void operationImpl1(String pMessage) {
implementation.operationImpl1(pMessage);
}

/**
* Lien vers la méthode operationImpl2() de l'implémentation
* @param pMessage
*/
protected void operationImpl2(Integer pNombre) {
implementation.operationImpl2(pNombre);
}
}
AbstractionA.java
/**
* Sous-classe concrète de l'abstraction
*/
public class AbstractionA extends Abstraction {

public AbstractionA(Implementation pImplementation) {
super(pImplementation);
}

public void operation() {
System.out.println("--> Méthode operation() de AbstractionA");
operationImpl1("A");
operationImpl2(1);
operationImpl1("B");
}
}
AbstractionB.java
/**
* Sous-classe concrète de l'abstraction
*/
public class AbstractionB extends Abstraction {

public AbstractionB(Implementation pImplementation) {
super(pImplementation);
}

public void operation() {
System.out.println("--> Méthode operation() de AbstractionB");
operationImpl2(9);
operationImpl2(8);
operationImpl1("Z");
}
}
BridgePatternMain.java
public class BridgePatternMain {

public static void main(String[] args) {
// Création des implémentations
Implementation lImplementationA = new ImplementationA();
Implementation lImplementationB = new ImplementationB();

// Création des abstractions
Abstraction lAbstractionAA = new AbstractionA(lImplementationA);
Abstraction lAbstractionAB = new AbstractionA(lImplementationB);
Abstraction lAbstractionBA = new AbstractionB(lImplementationA);
Abstraction lAbstractionBB = new AbstractionB(lImplementationB);

// Appels des méthodes des abstractions
lAbstractionAA.operation();
lAbstractionAB.operation();
lAbstractionBA.operation();
lAbstractionBB.operation();

// Affichage :
// --> Méthode operation() de AbstractionA
// operationImpl1 de ImplementationA : A
// operationImpl2 de ImplementationA : 1
// operationImpl1 de ImplementationA : B
// --> Méthode operation() de AbstractionA
// operationImpl1 de ImplementationB : A
// operationImpl2 de ImplementationB : 1
// operationImpl1 de ImplementationB : B
// --> Méthode operation() de AbstractionB
// operationImpl2 de ImplementationA : 9
// operationImpl2 de ImplementationA : 8
// operationImpl1 de ImplementationA : Z
// --> Méthode operation() de AbstractionB
// operationImpl2 de ImplementationB : 9
// operationImpl2 de ImplementationB : 8
// operationImpl1 de ImplementationB : Z
}
}
Comments