Monteur (patron de conception)
Un monteur (en anglais builder) est un patron de conception de création, principalement employé en programmation orientée objet, qui vise à séparer la construction d'un objet complexe de sa représentation afin qu'un même processus de construction puisse produire différentes représentations[1]. Le monteur fait partie des patrons dits « de création » popularisés par le recueil de 23 patrons souvent associé au « Gang of Four »[2].
Principe
[modifier | modifier le code]Le patron monteur s'applique lorsqu'un objet doit être construit en plusieurs étapes ou à partir de composants pouvant varier selon la représentation visée (par exemple, plusieurs variantes d'un même type d'objet). L'algorithme de construction (l'enchaînement des étapes) est séparé des détails d'assemblage, ce qui permet de faire varier la représentation finale en changeant le monteur utilisé, sans modifier l'algorithme de construction[1],[3].
Dans une présentation courante du patron, un « directeur » orchestre les appels de construction (ordre des étapes), tandis que le monteur fournit une interface de construction et encapsule la création et l'assemblage des parties constituant le produit final[3],[4]. Parmi les conséquences généralement mises en avant figurent la possibilité de faire varier la représentation interne du produit, l'isolation du code de construction et un contrôle plus fin sur le déroulement de la construction[3],[4].
Structure
[modifier | modifier le code]Une décomposition classique distingue les rôles suivants[3],[4] :
- Monteur : définit une interface de construction (méthodes correspondant aux étapes de création).
- Monteur concret : implémente l'interface du monteur et assemble les parties du produit.
- Directeur : pilote la construction en invoquant les étapes dans un ordre déterminé.
- Produit : objet complexe obtenu à l'issue des étapes de construction.
Diagramme de classes
[modifier | modifier le code]
Exemple
[modifier | modifier le code]Les exemples suivants (en Java et en PHP) illustrent le patron monteur à travers la création d'un objet Pizza (le produit) en trois étapes (pâte, sauce, garniture). Un directeur (Serveur) impose l'ordre des étapes et délègue l'assemblage à un monteur concret. Deux monteurs concrets produisent deux variantes de pizza.
Java
[modifier | modifier le code]/* Produit */
class Pizza {
private String pate = "";
private String sauce = "";
private String garniture = "";
public void setPate(String pate) { this.pate = pate; }
public void setSauce(String sauce) { this.sauce = sauce; }
public void setGarniture(String garniture) { this.garniture = garniture; }
}
/* Monteur */
abstract class MonteurPizza {
protected Pizza pizza;
public Pizza getPizza() { return pizza; }
public void creerNouvellePizza() { pizza = new Pizza(); }
public abstract void monterPate();
public abstract void monterSauce();
public abstract void monterGarniture();
}
/* Monteur concret */
class MonteurPizzaReine extends MonteurPizza {
public void monterPate() { pizza.setPate("croisée"); }
public void monterSauce() { pizza.setSauce("douce"); }
public void monterGarniture() { pizza.setGarniture("jambon+champignon"); }
}
/* Monteur concret */
class MonteurPizzaPiquante extends MonteurPizza {
public void monterPate() { pizza.setPate("feuilletée"); }
public void monterSauce() { pizza.setSauce("piquante"); }
public void monterGarniture() { pizza.setGarniture("pepperoni+salami"); }
}
/* Directeur */
class Serveur {
private MonteurPizza monteurPizza;
public void setMonteurPizza(MonteurPizza mp) { monteurPizza = mp; }
public Pizza getPizza() { return monteurPizza.getPizza(); }
public void construirePizza() {
monteurPizza.creerNouvellePizza();
monteurPizza.monterPate();
monteurPizza.monterSauce();
monteurPizza.monterGarniture();
}
}
/* Un client commandant des pizzas. */
class ExempleMonteur {
public static void main(String[] args) {
Serveur serveur = new Serveur();
MonteurPizza monteurPizzaReine = new MonteurPizzaReine();
MonteurPizza monteurPizzaPiquante = new MonteurPizzaPiquante();
serveur.setMonteurPizza(monteurPizzaReine);
serveur.construirePizza();
Pizza pizzaReine = serveur.getPizza();
serveur.setMonteurPizza(monteurPizzaPiquante);
serveur.construirePizza();
Pizza pizzaPiquante = serveur.getPizza();
}
}
Dans certaines API, les méthodes du monteur peuvent retourner l'instance du monteur (par exemple this), ce qui permet un chaînage d'appels (fluent interface)[5].
PHP
[modifier | modifier le code]/* Produit */
class Pizza {
private $_pate = "";
private $_sauce = "";
private $_garniture = "";
public function setPate($pate) { $this->_pate = $pate; }
public function setSauce($sauce) { $this->_sauce = $sauce; }
public function setGarniture($garniture) { $this->_garniture = $garniture; }
}
/* Monteur */
abstract class MonteurPizza {
protected $_pizza;
public function getPizza() { return $this->_pizza; }
public function creerNouvellePizza() { $this->_pizza = new Pizza(); }
abstract public function monterPate();
abstract public function monterSauce();
abstract public function monterGarniture();
}
/* Monteur concret */
class MonteurPizzaReine extends MonteurPizza {
public function monterPate() { $this->_pizza->setPate("croisée"); }
public function monterSauce() { $this->_pizza->setSauce("douce"); }
public function monterGarniture() { $this->_pizza->setGarniture("jambon+champignon"); }
}
/* Monteur concret */
class MonteurPizzaPiquante extends MonteurPizza {
public function monterPate() { $this->_pizza->setPate("feuilletée"); }
public function monterSauce() { $this->_pizza->setSauce("piquante"); }
public function monterGarniture() { $this->_pizza->setGarniture("pepperoni+salami"); }
}
/* Directeur */
class Serveur {
private $_monteurPizza;
public function setMonteurPizza(MonteurPizza $mp) { $this->_monteurPizza = $mp; }
public function getPizza() { return $this->_monteurPizza->getPizza(); }
public function construirePizza() {
$this->_monteurPizza->creerNouvellePizza();
$this->_monteurPizza->monterPate();
$this->_monteurPizza->monterSauce();
$this->_monteurPizza->monterGarniture();
}
}
/* Un client commandant des pizzas. */
$serveur = new Serveur();
$monteurPizzaReine = new MonteurPizzaReine();
$monteurPizzaPiquante = new MonteurPizzaPiquante();
$serveur->setMonteurPizza($monteurPizzaReine);
$serveur->construirePizza();
$pizzaReine = $serveur->getPizza();
$serveur->setMonteurPizza($monteurPizzaPiquante);
$serveur->construirePizza();
$pizzaPiquante = $serveur->getPizza();
Voir aussi
[modifier | modifier le code]Patrons associés
[modifier | modifier le code]Notes et références
[modifier | modifier le code]- 1 2 (en) Erich Gamma, Richard Helm, Ralph Johnson et John Vlissides, Design Patterns: Elements of Reusable Object-Oriented Software, Addison-Wesley, (ISBN 978-0-201-63361-0), p. 97
- ↑ (en) Frank Buschmann et Kevlin Henney, « Pattern-Oriented Software Architecture (tutorial) » [PDF], sur Vanderbilt University, (consulté le ), p. 66
- 1 2 3 4 (en) Douglas C. Schmidt, « Object-Oriented Patterns & Frameworks » [PDF], sur Vanderbilt University (consulté le ), p. 60-61
- 1 2 3 (en) Jerod Weinman, « A Brief Introduction to Design Patterns » [PDF], sur Grinnell College, Department of Computer Science (consulté le ), p. 8-9
- ↑ (en) « Lecture 17: Design patterns (CS 5150, Spring 2022) » [PDF], sur Department of Computer Science, Cornell University (consulté le ), p. 4-6