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

Observateur et état en Python

Après cette leçon: Je peux appliquer l’observateur pour prévenir plusieurs objets et l’état pour changer le comportement d’un objet.

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

Qu’est-ce que le patron observateur ?

Le patron observateur permet à un objet de prévenir automatiquement d’autres objets quand il change. L’objet observé ne connaît pas leurs détails : il sait seulement qu’il doit les prévenir. Il évite que le code qui change une valeur ait à penser à tout ce qui en dépend.

La cafétéria suit son stock de sandwichs. Quand il baisse, le journal le note et une alerte prévient le gérant.

À la fin de cette leçon

Remarque

Je peux appliquer l’observateur pour prévenir plusieurs objets et l’état pour changer le comportement d’un objet.

Mots-clés

MotCe que ça veut direExemple
Observateurun objet qui veut être prévenu d’un changement
Sujetl’objet observé, qui garde la liste de ses observateurs
S’abonnerse mettre sur la liste des objets prévenus
Notifierappeler chaque observateur quand il y a un changement
Étatla situation d’un objet qui décide de ce qu’il faitlecture, pause
Patron étatun objet par état, auquel on confie le comportement

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

Sans observateur, le stock connaît tout

Si la méthode qui change le stock appelle elle-même le journal, puis l’alerte, puis l’affichage, elle connaît tous ces objets. Chaque nouvel intéressé oblige à la rouvrir.

On retourne la dépendance : c’est le stock qui garde une liste, et chaque intéressé s’y inscrit.

Un stock qui prévient ses abonnés

Code: python
class Stock:
    def __init__(self, quantite):
        self.quantite = quantite
        self.observateurs = []

    def abonner(self, observateur):
        self.observateurs.append(observateur)

    def changer(self, quantite):
        self.quantite = quantite
        for observateur in self.observateurs:
            observateur.prevenir(quantite)


class Journal:
    def prevenir(self, quantite):
        print("Journal :", quantite)


stock = Stock(20)
stock.abonner(Journal())
stock.changer(12)
stock.changer(3)

Deux observateurs aux rôles différents

Le fichier des commandes ajoute un second observateur, Alerte. Le journal note chaque quantité. L’alerte ne parle que sous 5.

Le stock les traite de la même façon : il appelle prevenir sur chacun, dans l’ordre des abonnements.

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 le stock et ses observateurs

Commande
printf 'class Stock:\n    def __init__(self, quantite):\n        self.quantite = quantite\n        self.observateurs = []\n\n    def abonner(self, observateur):\n        self.observateurs.append(observateur)\n\n    def changer(self, quantite):\n        self.quantite = quantite\n        for observateur in self.observateurs:\n            observateur.prevenir(quantite)\n\n\nclass Journal:\n    def prevenir(self, quantite):\n        print("Journal :", quantite)\n\n\nclass Alerte:\n    def prevenir(self, quantite):\n        if quantite < 5:\n            print("Stock bas :", quantite)\n' > essais/stock.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.

Changer le stock deux fois

Commande
PYTHONPATH=essais python3 -c "from stock import Stock, Journal, Alerte; s = Stock(20); s.abonner(Journal()); s.abonner(Alerte()); s.changer(12); s.changer(3)"

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 patron état : un objet par situation

Un lecteur de musique réagit au bouton de façon différente selon qu’il est à l’arrêt, en lecture ou en pause. Une suite de if sur un texte devient vite illisible.

Avec le patron état, chaque situation est une classe. Le lecteur confie le bouton à l’objet état courant, qui rend l’état suivant.

Un lecteur et ses trois états

Code: python
class Arret:
    nom = "arret"
    def appuyer(self):
        return Lecture()


class Lecture:
    nom = "lecture"
    def appuyer(self):
        return Pause()


class Pause:
    nom = "pause"
    def appuyer(self):
        return Lecture()


class Lecteur:
    def __init__(self):
        self.etat = Arret()
    def appuyer(self):
        self.etat = self.etat.appuyer()


lecteur = Lecteur()
lecteur.appuyer()
print(lecteur.etat.nom)

Écrire le lecteur et ses états

Commande
printf 'class Arret:\n    nom = "arret"\n\n    def appuyer(self):\n        return Lecture()\n\n\nclass Lecture:\n    nom = "lecture"\n\n    def appuyer(self):\n        return Pause()\n\n\nclass Pause:\n    nom = "pause"\n\n    def appuyer(self):\n        return Lecture()\n\n\nclass Lecteur:\n    def __init__(self):\n        self.etat = Arret()\n\n    def appuyer(self):\n        self.etat = self.etat.appuyer()\n' > essais/lecteur.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.

Appuyer trois fois sur le bouton

Commande
PYTHONPATH=essais python3 -c "from lecteur import Lecteur; l = Lecteur(); l.appuyer(); print(l.etat.nom); l.appuyer(); print(l.etat.nom); l.appuyer(); print(l.etat.nom)"

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 confondent l’observateur et la stratégie. La stratégie est choisie une fois et on lui demande un calcul. L’observateur reçoit des nouvelles à chaque changement et ne rend rien. Retirez un observateur qui n’a plus besoin d’être prévenu.

Écrire le sujet d’un observateur

Dans le devoir, vous écrivez la classe Stock. abonner(observateur) et desabonner(observateur) gèrent la liste.

changer(quantite) range la nouvelle quantité, puis appelle prevenir(quantite) sur chaque abonné, dans l’ordre. Les tests lui donnent leurs propres observateurs.

À 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.