Design Pattern Facade

Description

Le design pattern facade fournit une interface qui offre une manière simplifiée d'accéder à un sous-système complexe. En d'autres termes, il permet de rendre simples certaines fonctionnalités d'un système compliqué en exposant certaines fonctionnalités.

Mise en situation

🖥️ Comment fonctionne un ordinateur ? Comme vous le savez, c'est un système complexe d'éléments interagissant ensemble :

  • 🧠 Le CPU : Il est le cerveau de notre ordinateur.
  • 💾 Les disques durs : Ils nous permettent de stocker des informations dans notre ordinateur.
  • 📝 Les rams : Permettent de mémoriser des données temporairement pour une exécution plus rapide.

Tous ces éléments composent un ordinateur, dans notre cas on peut dire que cet ordinateur est notre facade qui permettra d'exposer des fonctionnalités hors de toute la complexité des éléments. Notre sous-système représentera alors nos différents éléments de l'ordinateur exposé plus haut.

Avantages et inconvénients

Avantages Inconvénients
✔️Réduit la complexité ❌Complexité du code dans le cas où nous créons beaucoup de sous-systèmes.
✔️Isolation des sous-classes ❌Dépendance des sous-classes à l'interface, ce qui crée un couplage.
✔️Flexibilité

Quand l'utiliser ?

💡 Vous avez un sous-système complexe que vous voulez exposer simplement au client. 💡 Vous voulez structurer un sous-système sur plusieurs couches.

Diagramme UML

Dans le cas de cet exemple, nous développons un ordinateur qui affichera des messages de ses sous-systèmes. Jusqu'ici, le système est simple, mais comme vous le savez, un ordinateur peut devenir très vite complexe !

Face à cette situation, nous remarquons qu'un pattern facade est une très bonne solution.

Imaginons que l'on décide d'ajouter tous les composants d'un ordinateur et détailler leurs fonctionnements ? Dans notre cas, notre système devient complexe ! Complexe d'accord, mais nous voulons seulement exposer certaines fonctionnalités simples de notre système afin d'avoir une interactivité facile pour l'utilisateur. C'est pourquoi la création de notre facade représentera notre ordinateur. Ainsi, nous pourrons facilement ajouter ou retirer des éléments de notre sous-système dans cette interface sans lier les composants les uns aux autres.

Implémentation

Avant de créer notre facade, nous devons créer les composants de notre sous-système : CPU, Memory, HardDrive. Ici, nous allons afficher des messages simples caractérisant les différents éléments.

CPU

 package com.design.facade.subsystem;

public class CPU {
    public void freeze() {
        System.out.println("Computer freezing ... ");
    }

    public void jump(long position) {
        System.out.println("Jumping to..." + position);
    }

    public void execute() {
        System.out.println("Computer executing commands...");
    }
}

HardDrive

 package com.design.facade.subsystem;

public class HardDrive {

    public byte[] read(long Iba, int size) {
        return new byte[] {'f', 'z'};
    }
}

Memory

 package com.design.facade.subsystem;

public class Memory {

    public void load(long position, byte[] data) {
        System.out.println("Added item to memory.. " + position);
    }
}

Parfait ! Donc nos composants informatiques sont implémentés et nous avons assigné des comportements à chacun d'eux. Pour réaliser notre facade, nous allons lier ces éléments afin de les rendre disponibles plus facilement sous une interface commune.

BookDecorator

 package com.design.facade.facade;

import com.design.facade.subsystem.CPU;
import com.design.facade.subsystem.HardDrive;
import com.design.facade.subsystem.Memory;

public class  ComputerFacade {
    private CPU processor;
    private Memory ram;
    private HardDrive hardDrive;

    public ComputerFacade(CPU processor, Memory ram, HardDrive hardDrive) {
        this.processor = processor;
        this.ram = ram;
        this.hardDrive = hardDrive;
    }

    public void start() {
        processor.freeze();
        ram.load(132, hardDrive.read(3456, 89));
        processor.jump(132);
        processor.execute();
    }
}

Nous avons maintenant créé notre facade, qui nous a permis de simplifier les interactions de notre système par une seule méthode. Un peu comme dans la vie réelle, on appuie sur un bouton et tout s'exécute. Notre contrat est rempli, nous avons rendu un sous-système simplifié au client !

Maintenant, nous avons tout ce dont nous avons besoin pour tester notre code dans notre classe main ! Il nous reste à implémenter tout cela :

Main

 package com.design.facade;

import com.design.facade.facade.ComputerFacade;
import com.design.facade.subsystem.CPU;
import com.design.facade.subsystem.HardDrive;
import com.design.facade.subsystem.Memory;

public class Main {

    public static void main(String[] args) {
        ComputerFacade facade = new ComputerFacade(new CPU(), new Memory(), new HardDrive());
        facade.start();
    }
}

Resultat :

 Computer freezing ... 
Added item to memory.. 132
Jumping to...132
Computer executing commands...

Ici, nous avons donc fini notre implémentation. Ce que nous pouvons remarquer :

  • Nous avons exposé des fonctionnalités dans une facade de manière simple.
  • Notre système peut être étendu très simplement.
  • Nous pouvons ajouter des fonctionnalités sans impacter les autres.

Developpeur et architecte passionné, qui souhaite partagé son univers et ses découvertes afin de rendre les choses plus simple pour chacun