Plus facile à lire avec un fond crème, une teinte, plus de contraste ou un texte plus grand ? Choisissez vos couleurs et votre texte, une fois pour toutes les pages.

Leçon gratuite

Fabrique, stratégie et décorateur

Après cette leçon: Je peux appliquer une fabrique, une stratégie et un décorateur à un problème.

Leçon de 60 min5 commandesLab Linux du quotidien : la trentaine de commandes que les ingénieurs tapent de tête

Qu’est-ce qu’un patron de conception ?

Un patron de conception est une solution connue à un problème qui revient souvent dans la conception de classes. Il a un nom, ce qui permet de s’expliquer en un mot. Trois patrons très courants sont la fabrique, la stratégie et le décorateur.

La boutique de l’université applique des remises et vend des boissons avec des options. Chaque patron règle l’un de ces besoins.

À la fin de cette leçon

Remarque

Je peux appliquer une fabrique, une stratégie et un décorateur à un problème.

Mots-clés

MotCe que ça veut dire
Patron de conceptionune solution nommée à un problème fréquent
Fabriqueune fonction ou une classe qui crée le bon objet
Stratégieun objet qui contient une façon de faire, qu’on peut échanger
Décorateurun objet qui en enveloppe un autre pour lui ajouter un comportement
Même interfaceles objets échangés ont les mêmes méthodes
Enveloppel’objet qui contient un autre objet et l’appelle

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

La stratégie : une façon de faire qu’on échange

Une remise peut être nulle, de 20 pour cent, ou de 3 euros. Plutôt qu’un long if dans le panier, chaque remise est une petite classe avec une méthode appliquer.

Le panier reçoit un objet remise et lui délègue le calcul. Pour changer de remise, on donne un autre objet.

Des remises interchangeables

Code: python
class RemisePourcent:
    def __init__(self, pourcent):
        self.pourcent = pourcent

    def appliquer(self, prix):
        return prix - prix * self.pourcent // 100


class Panier:
    def __init__(self, remise):
        self.remise = remise
        self.somme = 0

    def ajouter(self, prix):
        self.somme = self.somme + prix

    def total(self):
        return self.remise.appliquer(self.somme)


panier = Panier(RemisePourcent(20))
panier.ajouter(600)
panier.ajouter(400)
print(panier.total())
panier.remise = RemisePourcent(50)
print(panier.total())

La fabrique choisit la bonne classe

Le programme lit le mot « etudiant » dans un formulaire. Quelle classe de remise faut-il créer ? Cette décision ne doit pas traîner partout.

Une fabrique la prend à un seul endroit : une fonction qui reçoit un nom et rend le bon objet. Le reste du programme n’a plus à connaître les classes.

Créer un dossier pour les essais

Commande
mkdir -p essais

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Écrire les remises et la fabrique

Commande
printf 'class RemiseAucune:\n    def appliquer(self, prix):\n        return prix\n\n\nclass RemisePourcent:\n    def __init__(self, pourcent):\n        self.pourcent = pourcent\n\n    def appliquer(self, prix):\n        return prix - prix * self.pourcent // 100\n\n\ndef creer_remise(nom):\n    if nom == "etudiant":\n        return RemisePourcent(20)\n    return RemiseAucune()\n' > essais/remises.py

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Demander une remise à la fabrique

Commande
PYTHONPATH=essais python3 -c "from remises import creer_remise; print(creer_remise('etudiant').appliquer(1000), creer_remise('plein').appliquer(1000))"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Le décorateur enveloppe un objet

Un café coûte 150 centimes. Le lait ajoute 30, le sucre 10. Une classe par combinaison serait absurde.

Un décorateur enveloppe un objet qui a la même interface. AvecLait(Cafe()) appelle le café, puis ajoute 30. On peut empiler les enveloppes dans l’ordre voulu.

Écrire le café et ses options

Commande
printf 'class Cafe:\n    def prix(self):\n        return 150\n\n\nclass AvecLait:\n    def __init__(self, boisson):\n        self.boisson = boisson\n\n    def prix(self):\n        return self.boisson.prix() + 30\n\n\nclass AvecSucre:\n    def __init__(self, boisson):\n        self.boisson = boisson\n\n    def prix(self):\n        return self.boisson.prix() + 10\n' > essais/cafe.py

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Empiler le lait et le sucre

Commande
PYTHONPATH=essais python3 -c "from cafe import Cafe, AvecLait, AvecSucre; print(AvecSucre(AvecLait(Cafe())).prix())"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Erreur fréquente

Attention

Beaucoup croient qu’il faut un patron partout, ou le choisissent avant d’avoir le problème. Partez du problème : une suite de if qui grossit appelle une stratégie. Le mot « décorateur » existe aussi en Python avec le signe @ : c’est un autre outil, qui ne fait pas partie de cette leçon.

Écrire le patron stratégie

Dans le devoir, vous écrivez trois remises : RemiseAucune, RemisePourcent(pourcent) et RemiseFixe(montant), qui ne descend jamais sous zéro.

Vous écrivez aussi Panier(remise) : ajouter(prix), total() qui applique la remise à la somme, et changer_remise(remise).

À propos de ce labo et de sa source: Lab Linux du quotidien : la trentaine de commandes que les ingénieurs tapent de tête

Vous enseignez à une classe ? Proposez ce module à vos étudiants avec un guide de l'enseignant, des devoirs corrigés et un laboratoire pour chaque étudiant.