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.
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 UML class diagram
(Ce qui précède est cité sur Wikipedia)
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.
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:*********************************************
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
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 classe
NumberGenerator` 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
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()
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
Le rôle de «ConcreteObserver» est le «Observateur» concret. Lorsque la méthode ʻupdateest appelée, elle obtient l'état actuel du rôle
Subject` 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)
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()
Recommended Posts