Facade pattern : interfaces uniformes pour les projets de logiciels
En recherchant des stratégies appropriées pour simplifier des logiciels complexes, on tombe inévitablement sur le design pattern facade (patron de conception de façade en français) ou patron de façade pour faire court. Avec d’autres modèles comme le pattern decorator ou le pattern composite, il appartient à la catégorie des patrons de structure des patrons de conception du « GoF » (pour « Gang of Four ») qui ont influencé de manière décisive la conception de logiciels depuis leur publication en 1994.
Vous apprendrez dans les paragraphes suivants ce qu’est exactement le patron de façade et comment il aide les développeurs à équilibrer les sous-systèmes.
Qu’est-ce que le facade pattern ?
Le patron de façade est un des 23 patrons de conception pour le développement de logiciels publiés en 1994 par Erich Gamma, Richard Helm, Ralph Johnson et John Vlissides (connus sous le nom de GOF pour « Gang of Four ») dans « Design Patterns : Elements of Reusable Object-Oriented Software ». Fidèle au principe général de ces patrons visant à simplifier la création de logiciels flexibles et réutilisables, le facade pattern propose une solution type pour fusionner facilement différentes interfaces dans des systèmes complexes. Une classe façade universelle, qui fonctionne également comme une interface, délègue des fonctionnalités importantes du logiciel aux sous-systèmes respectifs afin de rendre le maniement des différents sous-composants d’un programme aussi simple que possible.
Pour quels problèmes le facade pattern est-il une solution ?
Les clients qui ont accès à un sous-système complexe doivent directement faire face à une multitude d’objets ayant des interfaces complètement différentes ou dépendent de ces objets. Cela rend l’implémentation, la personnalisation, les tests et la réutilisation des clients particulièrement difficiles pour le développeur. C’est là que patron de façade intervient.
Le facade pattern prévoit la définition d’un objet de façade central (également appelé « façade ») qui :
- implémente une interface universelle pour les différentes interfaces du ou des sous-systèmes.
- et peut exécuter (si nécessaire) des fonctions supplémentaires avant ou après la transmission d’une demande du client.
En tant qu’intermédiaire, l’objet façade garantit que l’accès ou la communication avec les différents composants d’un sous-système est simplifié, réduisant ainsi la dépendance directe de ces composants au minimum. Il délègue les appels des clients afin que ceux-ci n’aient pas besoin de connaître les classes ou leurs relations et dépendances.
Facade pattern : représentation graphique (UML)
La façade ou classe façade est l’unité de structure la plus importante du patron de façade. Son implémentation et son élaboration constituent donc la tâche fondamentale des développeurs qui souhaitent simplifier leurs logiciels complexes en utilisant ce patron de conception pratique. Une fois implémentée, les objets clients concernés concentrent toute leur communication sur la classe façade, qui devient ainsi la seule instance de ce nouveau système dont les clients dépendent directement.
Le diagramme de classes qui suit, en langage de modélisation UML, explicite l’interaction des clients, de la façade et des classes de sous-systèmes selon le facade pattern.
Avantages et inconvénients du facade pattern
Les avantages du patron de façade sont évidents : la façade « cache » les sous-systèmes sous-jacents d’un logiciel et réduit ainsi leur complexité. En outre, cette solution favorise le principe du couplage faible. Grâce au faible degré de dépendance des différents composants les uns des autres, les changements (modifications, maintenance) sont possibles à tout moment et ne causent pas de désagréments majeurs, car ils n’ont la plupart du temps qu’un effet local. Ce couplage faible permet également de faciliter l’extension d’un sous-système.
Si les clients dépendent d’un accès direct à certaines classes du sous-système, celui-ci peut également être accordé dans le patron de façade : dans ce cas, seule la visibilité du sous-système doit être programmée afin qu’un client puisse contourner la façade si nécessaire.
Avantages | Inconvénients |
---|---|
Réduit la complexité des sous-systèmes | Implémentation complexe (surtout avec un code déjà existant) |
Favorise le principe du couplage faible | La solution est couplée à une étape indirecte supplémentaire |
Les logiciels sont plus flexibles et plus faciles à étendre | Degré élevé de dépendance de l’interface de la façade |
Scénarios d’application du facade pattern
Les propriétés du patron de façade sont intéressantes dans plusieurs scénarios d’utilisation. Le but premier est de disposer d’une interface uniforme pour accéder à des sous-systèmes complexes ou à un nombre infini d’objets. Une façade promet ici une grande simplification ; c’est pourquoi l’utilisation de la stratégie de patron de façade devrait jouer un rôle primordial dans la planification du projet.
Un autre cas d’utilisation typique est celui des logiciels où la dépendance entre les clients et les sous-systèmes sous-jacents doit être réduite au minimum.
Enfin, l’utilisation du patron de façade est payante lorsque vous planifiez un projet de logiciel qui doit être divisé en plusieurs couches. Les façades en tant qu’interfaces de communication entre les couches offrent également plus de flexibilité pour l’extension et l’adaptation ultérieures des composants.
Exemple de code : patron de façade
En tant que patron de conception, le facade pattern n’est pas lié à un langage de programmation spécifique. Cette solution est notamment utilisée en C++, C#, JavaScript, Java, PHP et Python. L’exemple de patron de façade suivant est basé sur un code Java. Pour cela, nous nous sommes inspirés du tutoriel de patron de façade trouvé sur tutorialspoint.
Dans cet exemple, une interface « Shape » applicable universellement doit être définie pour les objets représentant des formes géométriques. De plus, nous devrons générer des classes concrètes qui implémentent cette interface, ainsi qu’une classe façade appelée « ShapeMaker » qui est chargée de déléguer les demandes des clients.
Nous commençons par créer l’interface Shape.java avec le code suivant :
public interface Shape {
void draw();
}
La deuxième étape consiste à créer trois classes concrètes avec Rectangle.java (classe pour les objets rectangulaires), Square.java (classe pour les objets carrés) et Circle.java (classe pour les objets ronds), qui implémentent l’interface :
public class Rectangle implements Shape {
@Override
public void draw() {
System.out.println("Rectangle::draw()");
}
}
public class Square implements Shape {
@Override
public void draw() {
System.out.println("Rectangle::draw()");
}
}
public class Circle implements Shape {
@Override
public void draw() {
System.out.println("Rectangle::draw()");
}
}
Enfin, la classe façade ShapeMaker est intégrée dans le code. Les clients peuvent désormais y accéder pour générer les différentes formes :
public class ShapeMaker {
private Shape circle;
private Shape rectangle;
private Shape square;
public ShapeMaker() {
circle = new Circle();
rectangle = new Rectangle();
square = new Square();
}
public void drawCircle(){
circle.draw();
}
public void drawRectangle(){
rectangle.draw();
}
public void drawSquare(){
square.draw();
}
}