[GO] Apprenez le modèle de conception "Observer" en Python

En tant que matériel d'apprentissage des modèles de conception du GoF, le livre «Introduction aux modèles de conception appris dans le langage Java augmenté et révisé» semble être utile. Cependant, comme les exemples repris sont basés sur JAVA, j'ai essayé la même pratique avec Python pour approfondir ma compréhension.

■ Modèle d'observateur (modèle d'observateur)

Le modèle Observer est un type de modèle de conception utilisé dans le processus de notification à d'autres objets des événements (événements) d'un objet dans le programme. Ceci est appelé parce que le côté objet à notifier est observé par le côté objet à notifier (anglais: observer). Également appelé modèle d'abonnement à la publication. Il est étroitement lié au principe de l'appel implicite. Il est également utilisé pour implémenter un système de traitement d'événements distribué. Selon la langue, les problèmes traités dans ce modèle sont traités par la syntaxe de gestion des événements du langage.

UML class and sequence diagram W3sDesign_Observer_Design_Pattern_UML.jpg UML class diagram 2880px-Observer_w_update.svg.png

(Ce qui précède est cité sur Wikipedia)

□ Mémorandum

Dans le modèle ʻObserver, lorsque l'état de la cible d'observation change, l'observateur est notifié, donc cela semble être efficace pour décrire le traitement en fonction du changement d'état. La signification originale du mot «observateur» est «observateur», mais en réalité, le rôle de «observateur» n'est pas «d'observer» activement mais d'être passivement «notifié» par le rôle de «sujet». On dit qu'il est parfois appelé le modèle Publish-Subscribe` car il vous attendra. Certes, j'ai pensé que les expressions «publier» et «s'abonner» étaient plus appropriées.

■ Exemple de programme "Observer"

Je voudrais exécuter un exemple de programme qui utilise le modèle Observer et vérifier le comportement suivant.

――L'observateur observe l'objet qui génère beaucoup de nombres et affiche la valeur. ――La méthode d'affichage diffère selon l'observateur. --DigitalObserver affiche la valeur numériquement --GraphicObserver affiche les valeurs dans un graphique simple

$ python Main.py 
DigitObservser: 30
GraphicObserver:******************************
DigitObservser: 48
GraphicObserver:************************************************
DigitObservser: 6
GraphicObserver:******
DigitObservser: 19
GraphicObserver:*******************
DigitObservser: 19
GraphicObserver:*******************
DigitObservser: 45
GraphicObserver:*********************************************
DigitObservser: 8
GraphicObserver:********
DigitObservser: 21
GraphicObserver:*********************
DigitObservser: 40
GraphicObserver:****************************************
DigitObservser: 6
GraphicObserver:******
DigitObservser: 1
GraphicObserver:*
DigitObservser: 9
GraphicObserver:*********
DigitObservser: 26
GraphicObserver:**************************
DigitObservser: 22
GraphicObserver:**********************
DigitObservser: 16
GraphicObserver:****************
DigitObservser: 10
GraphicObserver:**********
DigitObservser: 45
GraphicObserver:*********************************************
DigitObservser: 1
GraphicObserver:*
DigitObservser: 36
GraphicObserver:************************************
DigitObservser: 45
GraphicObserver:*********************************************

■ Détails de l'exemple de programme

Un code similaire a été téléchargé dans le référentiel Git. https://github.com/ttsubo/study_of_design_pattern/tree/master/Observer

.
├── Main.py
└── observer
    ├── __init__.py
    ├── generator.py
    └── observer.py

(1) Rôle du sujet

Le rôle «Sujet» représente le «côté observé». Le rôle Subject a une méthode pour enregistrer le rôle d'observateur ʻObserveret une méthode pour le supprimer. Il déclare également une méthode "obtenir l'état actuel". Dans l'exemple de programme, la classeNumberGenerator` remplit ce rôle.

observer/generator.py


import random
from abc import ABCMeta, abstractmethod

class NumberGenerator(metaclass=ABCMeta):
    def __init__(self):
        self.__observers = []

    def addObserver(self, observer):
        self.__observers.append(observer)

    def deleteObserver(self, observer):
        self.__observers.remove(observer)

    def notifyObserver(self):
        for o in self.__observers:
            o.update(self)

    @abstractmethod
    def getNumber(self):
        pass

    @abstractmethod
    def execute(self):
        pass

(2) Le rôle du sujet concret

Le rôle «Sujet concret» est un rôle qui exprime un «côté observé» concret. Lorsque l'état change, indiquez-lui le rôle «Observateur» enregistré. Dans l'exemple de programme, la classe RandomNumberGenerator remplit ce rôle.

observer/generator.py


class RandomNumberGenerator(NumberGenerator):
    def __init__(self):
        self.__number = 0
        super(RandomNumberGenerator, self).__init__()

    def getNumber(self):
        return self.__number

    def execute(self):
        for _ in range(20):
            self.__number = random.randint(0, 49)
            self.notifyObserver()

(3) Le rôle de l'observateur (observateur)

Le rôle de ʻObserver est le rôle d'être informé par le rôle de Sujet que "l'état a changé". La méthode pour cela est ʻupdate. Dans l'exemple de programme, la classe ʻObserver` remplit ce rôle.

observer/observer.py


import time
from abc import ABCMeta, abstractmethod

class Observer(metaclass=ABCMeta):
    @abstractmethod
    def update(self, ganerator):
        pass

(4) Le rôle de ConcreteObserver (observateur concret)

Le rôle de «ConcreteObserver» est le «Observateur» concret. Lorsque la méthode ʻupdateest appelée, elle obtient l'état actuel du rôleSubject` dans cette méthode. Dans l'exemple de programme, les classes «DigitObserver» et «GraphObserver» remplissent ce rôle.

observer/observer.py


class DigitObserver(Observer):
    def update(self, generator):
        print("DigitObservser: {0}".format(generator.getNumber()))
        time.sleep(0.1)


class GraphObserver(Observer):
    def update(self, generator):
        print("GraphicObserver:", end='')
        count = generator.getNumber()
        for _ in range(count):
            print('*', end='')
        print("")
        time.sleep(0.1)

(5) Le rôle du client

Dans l'exemple de programme, la méthode startMain remplit ce rôle.

Main.py


from observer.observer import  DigitObserver, GraphObserver
from observer.generator import RandomNumberGenerator

def startMain():
    generator = RandomNumberGenerator()
    observer1 = DigitObserver()
    observer2 = GraphObserver()
    generator.addObserver(observer1)
    generator.addObserver(observer2)
    generator.execute()

if __name__ == '__main__':
    startMain()

■ URL de référence

Recommended Posts

Apprenez le modèle de conception "Observer" en Python
Apprenez le modèle de conception "Prototype" avec Python
Apprenez le modèle de conception "Flyweight" en Python
Apprenez le modèle de conception "Memento" avec Python
Apprenez le modèle de conception "Proxy" en Python
Apprenez le modèle de conception "Commande" en Python
Apprenez le modèle de conception "Visiteur" avec Python
Apprenez le modèle de conception "Bridge" avec Python
Apprenez le modèle de conception "Mediator" avec Python
Apprenez le modèle de conception "Décorateur" avec Python
Apprenez le modèle de conception "Iterator" avec Python
Apprenez le modèle de conception «Stratégie» avec Python
Apprenez le modèle de conception "Composite" avec Python
Apprenez le modèle de conception "État" en Python
Apprenez le modèle de conception "Adapter" avec Python
Apprenez le modèle de conception "Abstract Factory" avec Python
Apprenez le modèle de conception "Méthode de modèle" en Python
Apprenez le modèle de conception "Méthode d'usine" en Python
Apprenez le modèle de conception «Chaîne de responsabilité» en Python
Apprenez le modèle de conception "Singleton" avec Python
Apprenez le modèle de conception "Façade" avec Python
Implémenter le modèle Singleton en Python
Modèle de conception #Observer
Motif singleton en Python
Modèle d'observateur en Java
Modèle de visiteur en Python
Trouver des erreurs en Python
Modèles de conception en Python: introduction
Python Design Pattern - Méthode de modèle
Obtenir l'API arXiv en Python
Python dans le navigateur: la recommandation de Brython
Enregistrez le fichier binaire en Python
Frappez l'API Sesami en Python
Obtenez le chemin du bureau en Python
Obtenez le chemin du script en Python
Dans la commande python, python pointe vers python3.8
Accédez à l'API Web en Python
J'ai écrit la file d'attente en Python
Calculer le mois précédent en Python
Examiner la classe d'un objet avec python
Obtenez le chemin du bureau en Python
Obtenez le nom d'hôte en Python
Accéder à l'API Twitter avec Python
La première étape de Python Matplotlib
J'ai écrit la pile en Python
Maîtriser le module lowref en Python
Apprenez les bases de Python ① Débutants élémentaires
Charger le SDK Python distant avec IntelliJ
Essayez d'utiliser l'API Wunderlist en Python
[Python Kivy] À propos de la modification du thème de conception
Essayez d'utiliser l'API Kraken avec Python
Apprenez les bases en touchant les variables python
Ecrire le test dans la docstring python
Prenez la somme logique de List en Python (fonction zip)
Modèle de conception du GoF à partir du problème 2. Structure
Afficher Python 3 dans le navigateur avec MAMP
Tweet à l'aide de l'API Twitter en Python
Vérifiez si l'URL existe en Python