Adaptateur (patron de conception)

Un article de Wikipédia, l'encyclopédie libre.
Aller à : navigation, rechercher

En génie logiciel, Adaptateur (ou Wrapper[1]) 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[2].

Applicabilité[modifier | modifier le code]

Il permet d'intégrer une classe à ne pas modifier[3], 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.

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.

Structure[modifier | modifier le code]

Schéma UML du motif de conception Adaptateur
  • IAdaptateur : définit l'interface métier utilisée par le Client.
  • Client : travaille avec des objets utilisant l'interface IAdaptateur.
  • Adapté : définit une interface existante devant être adaptée.
  • Adaptateur : fait correspondre l'interface de Adapté à l'interface IAdaptateur.

Mise en œuvre[modifier | modifier le code]

Exemple en C++[modifier | modifier le code]

Un adaptateur pour faire un carré aux coins ronds. Le code est en C++.

class Carre{
  public:
    Carre();
    virtual dessineCarre();
    virtual Coordonnees *getQuatreCoins();
};

class Cercle{
  public:
    Cercle();
    virtual dessineCercle();
    virtual void setArc1(Coordonnees *c1);
    virtual void setArc2(Coordonnees *c2);
    virtual void setArc3(Coordonnees *c3);
    virtual void setArc4(Coordonnees *c4);
    virtual Coordonnees *getCoordonneesArc();
};

class CarreCoinsRondAdaptateur: public Carre, private Cercle{
  public:
    CarreCoinsRondAdaptateur();
    virtual void dessineCarre(){
       setArc1(new Coordonnees(0,0));
       setArc2(new Coordonnees(4,0));
       setArc3(new Coordonnees(4,4));
       setArc4(new Coordonnees(0,4));
       // Fonction qui dessine les lignes entre les arcs
       dessineCercle();
    }
    virtual Coordonnees *getQuatreCoins(){
       return getCoordonneesArc();
    }
};

Exemple en C♯[modifier | modifier le code]

En C♯ :

/// <summary> la signature "IAdaptateur" utilisée par le client </summary>
public interface IDeveloppeur {
    /// <summary>  Requete </summary>
    string EcrireCode();
}

/// <summary> concrétisation normale de "IAdaptateur" par une classe </summary>
class DeveloppeurLambda : IDeveloppeur {
    public string EcrireCode() { 
        return "main = putStrLn \"Algorithme codé\""; 
    }
}

/// <summary> "Adapté" qui n'a pas la signature "IAdaptateur" </summary>
class Architecte {
    public string EcrireAlgorithme() { 
        return "Algorithme";
    }
}

/// <summary> "Adaptateur" qui encapsule un objet qui n'a pas la bonne signature</summary>
class Adaptateur : IDeveloppeur {
    Architecte _adapté;
    public Adaptateur (Architecte adapté) {
        _adapté = adapté;
    }
    public string EcrireCode() {
        string algorithme = _adapté.EcrireAlgorithme();
        return string.Format("let main() = printfn \"{0} codé\"", algorithme);
    }
}

//___________________________________________________________________
// Mise en œuvre

/// <summary> "Client" qui n'utilise que les objets qui respectent la signature </summary>
class Client {
    void Utiliser(IDeveloppeur cible) {
        string code = cible.EcrireCode();
        Console.WriteLine(code);
    }
    static void Main() {
        var client = new Client();

        IDeveloppeur cible1 = new DeveloppeurLambda();
        client.Utiliser(cible1);

        var adapté = new Architecte();
        IDeveloppeur cible2 = new Adaptateur(adapté);
        client.Utiliser(cible2);
    }
}

Utilisations connues[modifier | modifier le code]

On peut également utiliser un adaptateur lorsque l'on ne veut pas développer toutes les méthodes d'une certaine interface[réf. nécessaire]. Par exemple, si l'on doit développer l'interface MouseListener en Java, mais que l'on ne souhaite pas développer de comportement pour toutes les méthodes, on peut dériver la classe MouseAdapter. Celle-ci fournit en effet un comportement par défaut (vide) pour toutes les méthodes de MouseListener.

Exemple avec le MouseAdapter :

 public class MouseBeeper extends MouseAdapter
 {
   public void mouseClicked(MouseEvent e) {
     Toolkit.getDefaultToolkit().beep();
   }
 }

Exemple avec le MouseListener :

 public class MouseBeeper implements MouseListener
 {
   public void mouseClicked(MouseEvent e) {
     Toolkit.getDefaultToolkit().beep();
   }

   public void mousePressed(MouseEvent e) {}
   public void mouseReleased(MouseEvent e) {}
   public void mouseEntered(MouseEvent e) {}
   public void mouseExited(MouseEvent e) {}
 }

Notes et références[modifier | modifier le code]

  1. http://rpouiller.developpez.com/tutoriel/java/design-patterns-gang-of-four/?page=page_3
  2. Adaptateur sur DoFactory
  3. Conception d'applications en Java/JEE : Principes, patterns et architectures, Dunod,‎ (lire en ligne)

Voir aussi[modifier | modifier le code]

Sur les autres projets Wikimedia :

Articles connexes[modifier | modifier le code]