SOLDES de printemps

Façade

Alias : Facade

Intention

Façade est un patron de conception structurel qui procure une interface offrant un accès simplifié à une librairie, un framework ou à n’importe quel ensemble complexe de classes.

Patron de conception façade

Problème

Imaginez que vous devez adapter votre code pour manipuler un ensemble d’objets qui appartiennent à une librairie ou à un framework assez sophistiqué. D’ordinaire, vous initialisez tous ces objets en premier, gardez la trace des dépendances et appelez les méthodes dans le bon ordre, etc.

Par conséquent, la logique métier de vos classes devient fortement couplée avec les détails de l’implémentation des classes externes, rendant cette logique difficile à comprendre et à maintenir.

Solution

Une façade est une classe qui procure une interface simple vers un sous-système complexe de parties mobiles. Les fonctionnalités proposées par la façade seront plus limitées que si vous interagissiez directement avec le sous-système, mais vous pouvez vous contenter de n’inclure que les fonctionnalités qui intéressent votre client.

Une façade se révèle très pratique si votre application n’a besoin que d’une partie des fonctionnalités d’une librairie sophistiquée parmi les nombreuses qu’elle propose.

Par exemple, une application qui envoie des petites vidéos de chats comiques sur des réseaux sociaux peut potentiellement utiliser une librairie de conversion vidéo professionnelle. Mais la seule chose dont vous ayez réellement besoin, c’est d’une classe dotée d’une méthode encoder(fichier, format). Après avoir créé cette classe et intégré la librairie de conversion vidéo, votre façade est opérationnelle.

Analogie

Un exemple d’un passage de commande au téléphone

Passer une commande au téléphone.

Lorsque vous téléphonez à un magasin pour commander, un opérateur joue le rôle de la façade pour tous ses services. L’opérateur vous sert d’interface vocale avec le système de commandes, les moyens de paiement et les différents services de livraison.

Structure

Structure du patron de conception façadeStructure du patron de conception façade
  1. La Façade procure un accès pratique aux différentes parties des fonctionnalités du sous-système. Elle sait où diriger les requêtes du client et comment utiliser les différentes parties mobiles.

  2. Une classe Façade Supplémentaire peut être créée pour éviter de polluer une autre façade avec des fonctionnalités qui pourraient la rendre trop complexe. Les façades supplémentaires peuvent être utilisées à la fois par le client et par les autres façades.

  3. Le Sous-système Complexe est composé de dizaines d’objets variés. Pour leur donner une réelle utilité, vous devez plonger au cœur des détails de l’implémentation du sous-système, comme initialiser les objets dans le bon ordre et leur fournir les données dans le bon format.

    Les classes du sous-système ne sont pas conscientes de l’existence de la façade. Elles opèrent et interagissent directement à l’intérieur de leur propre système.

  4. Le Client passe par la façade plutôt que d’appeler les objets du sous-système directement.

Pseudo-code

Dans cet exemple, la Façade simplifie l’interaction avec un framework complexe de conversion vidéo.

La structure de la façade dans l’exemple utilisé

Utilisation d’une classe façade dans un exemple d’isolation de dépendances multiples.

Plutôt que d’adapter directement la base de votre code à des dizaines de classes, vous créez une façade qui permet d’encapsuler cette fonctionnalité et de la cacher du reste du code. Cette structure permet de minimiser le travail nécessaire aux futures évolutions du framework, ou au remplacement de ce dernier par un autre. Vous pouvez vous contenter de modifier l’implémentation des méthodes de la façade.

// Voici quelques classes d’un framework complexe de conversion
// vidéo externe. Nous n’avons pas la main sur le code, nous ne
// pouvons donc pas le simplifier.
class VideoFile
// ...

class OggCompressionCodec
// ...

class MPEG4CompressionCodec
// ...

class CodecFactory
// ...

class BitrateReader
// ...

class AudioMixer
// ...


// Nous créons une classe façade pour cacher la complexité du
// framework derrière une interface simple. C’est un compromis
// entre fonctionnalité et simplicité.
class VideoConverter is
    method convert(filename, format):File is
        file = new VideoFile(filename)
        sourceCodec = (new CodecFactory).extract(file)
        if (format == "mp4")
            destinationCodec = new MPEG4CompressionCodec()
        else
            destinationCodec = new OggCompressionCodec()
        buffer = BitrateReader.read(filename, sourceCodec)
        result = BitrateReader.convert(buffer, destinationCodec)
        result = (new AudioMixer()).fix(result)
        return new File(result)

// Les classes application ne dépendent pas d’un milliard de
// classes fournies par un framework complexe. Si vous décidez
// de changer de framework, vous avez seulement besoin de
// réécrire la classe façade.
class Application is
    method main() is
        convertor = new VideoConverter()
        mp4 = convertor.convert("funny-cats-video.ogg", "mp4")
        mp4.save()

Possibilités d’application

Utilisez la façade si vous avez besoin d’une interface limitée mais directe à un sous-système complexe.

Souvent, les sous-systèmes gagnent en complexité avec le temps et mettre en place un patron de conception implique de créer de nouvelles classes. Dans de nombreux contextes, un sous-système peut se révéler plus souple et facile à réutiliser, mais la quantité de travail pour configurer et écrire le code de base ne fait que croitre. La façade tente de remédier à ce problème en fournissant un raccourci aux fonctionnalités du sous-système qui sont adaptées au besoin du client.

Utilisez la façade si vous voulez structurer un sous-système en plusieurs couches.

Créez des façades pour définir des points d’entrée à chaque niveau d’un sous-système. Vous pouvez réduire le couplage entre plusieurs sous-systèmes en les obligeant à communiquer au travers de façades.

Reprenons notre exemple de framework de conversion vidéo. Il peut être désassemblé en deux couches : tout ce qui concerne la vidéo d’un côté et l’audio de l’autre. Créez une façade pour chaque couche. Vous pouvez utiliser ce genre de façades pour faire communiquer les classes de ces couches ensemble. Cette approche peut fortement ressembler au patron de conception Médiateur.

Mise en œuvre

  1. Vérifiez s’il est possible de fournir une interface plus simple que ce qu’un sous-système vous propose. Si cette interface peut découpler le code client des nombreuses classes du sous-système, vous êtes sur la bonne voie !

  2. Déclarez et implémentez cette interface en tant que nouvelle façade. Elle doit rediriger les appels du code client aux objets appropriés du sous-système. Elle doit également être responsable de l’initialisation du sous-système et gérer son cycle de vie, sauf si le code client s’en occupe déjà.

  3. Pour exploiter au maximum les avantages de la façade, toute communication du code client avec le sous-système doit passer par elle. Cette manipulation protège le code client de tout effet de bord que des modifications apportées au sous-système pourraient provoquer. Si un sous-système est mis à jour, vous n’aurez besoin que de modifier le code de la façade.

  4. Si la façade devient trop grande, vous devriez envisager de transférer une partie de ses comportements vers une nouvelle façade plus spécialisée.

Avantages et inconvénients

  • Vous pouvez isoler votre code de la complexité d’un sous-système.
  • Une façade peut devenir un objet omniscient couplé à toutes les classes d’une application.

Liens avec les autres patrons

  • La Façade définit une nouvelle interface pour les objets existants, alors que l’Adaptateur essaye de rendre l’interface existante utilisable. L’adaptateur emballe généralement un seul objet alors que la façade s’utilise pour un sous-système complet d’objets.

  • La Fabrique abstraite peut remplacer la Façade si vous voulez simplement cacher au code client la création des objets du sous-système.

  • Le Poids mouche vous montre comment créer plein de petits objets alors que la Façade permet de créer un seul objet qui représente un sous-système complet.

  • La Façade et le Médiateur ont des rôles similaires : ils essayent de faire collaborer des classes étroitement liées.

    • La façade définit une interface simplifiée pour un sous-système d’objets, mais elle n’ajoute pas de nouvelles fonctionnalités. Le sous-système lui-même n’a pas connaissance de la façade. Les objets situés à l’intérieur du sous-système peuvent communiquer directement.
    • Le médiateur centralise la communication entre les composants du système. Les composants ne voient que l’objet médiateur et ne communiquent pas directement.
  • Une classe Façade peut souvent être transformée en Singleton, car un seul objet façade est en général suffisant.

  • La Façade et la Procuration ont une similarité : ils mettent en tampon une entité complexe et l’initialisent individuellement. Contrairement à la façade, la procuration implémente la même interface que son objet service, ce qui les rend interchangeables.

Exemples de code

Façade en C# Façade en C++ Façade en Go Façade en Java Façade en PHP Façade en Python Façade en Ruby Façade en Rust Façade en Swift Façade en TypeScript