Qu’est-ce que le « builder pattern » ?

Le builder pattern fait partie des design patterns, c’est-à-dire des patrons de conception qui permettent de résoudre les problèmes de programmation dans la programmation orientée objet (POO). Ils facilitent la programmation pour les développeurs : ainsi, vous n’avez pas à repenser la routine de chaque étape récurrente puisque des propriétés qui peuvent être modifiées ont déjà été établies. Ces éléments de logiciel remontent au livre « Design patterns. Catalogue des modèles de conception réutilisables » sorti en 1994 et rédigé par quatre informaticiens américains connus sous le nom de Gang of Four (bande des quatre). Notre guide vous présente les aspects essentiels du builder pattern, ou patron de conception monteur, à l’aide d’un exemple pratique.

Qu’est-ce que le builder pattern ?

Le patron builder appartient au groupe des patrons de création. Il améliore la sécurité lors de la programmation ainsi que la lisibilité du code. L’objectif du patron de conception monteur est de créer un objet au moyen d’une classe utilitaire, et non avec les constructeurs connus.

Citation

„Separate the construction of a complex object from its representation so that the same construction process can create different representations.“

Traduction : « Dissocier la construction d’un objet complexe de sa représentation, afin que le même processus de construction puisse créer des représentations différentes. » (Traduction de IONOS)

– Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (= « Gang of Four »)

Source : Design Patterns: Elements of Reusable Object-Oriented Software (anglais) 1ère édition, éditeur : Addison-Wesley Professional; 1ère édition (10 novembre 1994)

Dans le patron builder, on distingue quatre classes :

  • Directeur : cette classe ne construit pas l’objet complexe directement, mais utilise plutôt l’interface du monteur pour créer les différentes parties de l’objet et les assembler. Il connaît les séquences de montage du monteur. Avec le directeur, la création d’un objet est dissociée du client.
  • Monteur : fournit une interface permettant de créer les composants d’un objet (ou d’un produit) complexe.
  • MonteurConcret : cette classe construit les différentes parties de l’objet complexe. Il définit et gère également la représentation du produit qu’il crée.
  • Produit : le résultat de « l’activité » du patron Builder, c’est-à-dire l’objet complexe à construire.

Avec le directeur, l’étape cruciale du patron de conception monteur a lieu, la séparation de la construction d’un objet/produit du client.

Le builder pattern : représentation graphique (UML)

Pour la représentation graphique des séquences de programmation, le langage de modélisation unifié, en abrégé UML (Unified Modeling Language), est utilisé. Le diagramme montre que le modèle de construction est constitué de plusieurs objets agissant ensemble.

Avantages et inconvénients du builder pattern

Avantages du patron de conception monteur

La construction (le montage) et la représentation (la production) sont intégrées de manière isolée l’une de l’autre. Les représentations internes des monteurs sont « cachées » au directeur. De nouvelles représentations peuvent être facilement insérées grâce à de nouvelles classes de monteurConcret. Le processus de construction est contrôlé par le directeur. Si des modifications doivent être apportées au cours du processus, cela peut se faire sans consulter le client.

Inconvénients du patron de conception monteur

Il existe un lien étroit entre le produit, le monteurConcret et les classes impliquées dans le processus de construction, de sorte qu’il peut être difficile de modifier le processus de base. La construction d’objets nécessite souvent des connaissances sur leur utilisation et leur environnement spécifiques. L’utilisation de modèles familiers, tels que le patron de conception monteur, peut amener les programmeurs à négliger des solutions plus simples et peut-être plus élégantes. Au final, le builder pattern est considéré comme un des patrons de conception les moins importants.

Scénarios d’application du builder pattern ?

Afin d’illustrer le patron de conception monteur, prenons l’image d’un restaurant où un client commande un menu. Les différents acteurs du restaurant agissent dès réception de la commande pour la réaliser. L’ensemble du processus menant à la réception du menu commandé se déroule « en coulisses ». Le client ne voit pas, par exemple, ce qui se passe dans la cuisine pour honorer sa commande : on lui sert le résultat à sa table (en langage de programmation : imprimé = print).

Les parties du code qui suivent présentent toutes les classes du builder pattern séparément.

L’objet, le menu complet, est initialement vide ; il se remplit lorsque la commande arrive.

public class Menu {
	private String starter = "Pas d’entrée";
	private String maincourse = "Pas de plat principal";
	private String dessert = "Pas de dessert";
	private String drink = "Pas de boisson";
	public void setEntree(String starter) {
		this.starter = starter;
	}
	public void setPlatPrincipal(String maincourse) {
		this.maincourse = maincourse;
	}
	public void setDessert(String dessert) {
		this.dessert = dessert;
	}
	public void setBoisson(String drink) {
		this.drink = drink;
	}
	public void print() {
		System.out.println(
			"Le menu est prêt ! " + "\n" +
			" – Entrée: " + starter +
			" – Plat principal: " + maincourse +
			" – Dessert: " + dessert +
			" – Boisson: " + drink);
	}
}

Le directeur fournit un « environnement » dans lequel un menu peut être produit (monté) pour l’invité. Cet environnement est accessible à tous les invités. L’invité communique exclusivement avec le directeur, de sorte que la production proprement dite lui reste cachée :

public class MattsRestaurant {
	private MenuBuilder menuBuilder;
	public void setBuilder(MenuBuilder menuBuilder) {
		this.menuBuilder = menuBuilder;
	}
	public Menu buildMenu(){
		menuBuilder.buildStarter();
		menuBuilder.buildMainCourse();
		menuBuilder.buildDessert();
		menuBuilder.buildDrink();
		return menuBuilder.build();
	}
}

Ensuite, le monteur passe à l’action. Dans l’exemple choisi, il s’agirait d’un chef cuisinier :

public abstract class MenuBuilder {
	Menu menu = new Menu();
	abstract void buildStarter();
	abstract void buildMainCourse();
	abstract void buildDessert();
	abstract void buildDrink();
	Menu build()
{
		return menu;
	}
}

Le monteurConcret, dans ce cas le cuisinier, monte (construit/cuit) les différents éléments du menu commandé. Pour ce faire, il redéfinie (override) les éléments de menu « abstraits » existants :

public class MenuOfTheDayBuilder extends MenuBuilder {
	@Override
	public void buildStarter() {
		burger.setStarter("Soupe de potiron");
	}
	@Override
	public void buildMainCourse() {
		burger.setMainCourse("Steak frites");
	}
	@Override
	public void buildDessert() {
		burger.setDessert("Glace à la vanille");
	}
	@Override
	public void buildDrink() {
		burger.setDrink("Vin rouge");
	}
}

Enfin, les points individuels sont exécutés de façon sommaire et livrés à l’invité, c’est-à-dire « imprimés » dans le langage de programmation :

public class Main {
	public static void main(String[] args) {
		MattsRestaurant mattsRestaurant = new MattsRestaurant();
		menuRestaurant.setBuilder(new MenuOfTheDayBuilderBuilder());
		buildMenu(menuRestaurant);
		menuRestaurant.setBuilder(new SpecialMenuBuilder());
		buildMenu(menuRestaurant);
	}
	private static void buildMenu(MattsRestaurant mattsRestaurant) {
		MenuOfTheDay menu = mattsRestaurant.buildMenu();
		menu.print();
	}
}
Note

L’exemple choisi est basé sur les codes de Daniel Høyer Jacobsen, qui présente plusieurs illustrations de patrons de conception en Java sur son site Web.