Als Material zum Erlernen von GoF-Entwurfsmustern scheint das Buch "Einführung in Entwurfsmuster, die in der erweiterten und überarbeiteten Java-Sprache gelernt wurden" hilfreich zu sein. Da die aufgeführten Beispiele jedoch auf JAVA basieren, habe ich dieselbe Vorgehensweise mit Python versucht, um mein Verständnis zu vertiefen.
Das Observer-Muster ist eine Art Entwurfsmuster, das beim Benachrichtigen anderer Objekte über Ereignisse (Ereignisse) eines Objekts im Programm verwendet wird. Dies wird aufgerufen, weil die zu benachrichtigende Objektseite von der zu benachrichtigenden Objektseite beobachtet wird (Englisch: beobachten). Wird auch als Publishing-Abonnement-Modell bezeichnet. Es ist eng mit dem Prinzip des impliziten Aufrufs verbunden. Es wird auch verwendet, um ein verteiltes Ereignisverarbeitungssystem zu implementieren. Abhängig von der Sprache werden die in diesem Muster behandelten Probleme von der Ereignisbehandlungssyntax der Sprache behandelt.
UML class and sequence diagram UML class diagram
(Das Obige ist aus Wikipedia zitiert)
Wenn sich im "Beobachter" -Muster der Zustand des Beobachtungsziels ändert, wird der Beobachter benachrichtigt, so dass es bei der Beschreibung der Verarbeitung gemäß der Zustandsänderung wirksam zu sein scheint. Die ursprüngliche Bedeutung des Wortes "Beobachter" ist "Beobachter", aber in Wirklichkeit ist die Rolle des "Beobachters" nicht aktiv "beobachten", sondern wird passiv durch die Rolle des "Subjekts" "benachrichtigt". Es wird gesagt, dass es manchmal als "Publish-Subscribe" -Muster bezeichnet wird, weil es auf Sie wartet. Natürlich fand ich die Ausdrücke "veröffentlichen" und "abonnieren" angemessener.
Ich möchte tatsächlich ein Beispielprogramm ausführen, das das Observer-Muster verwendet, und das folgende Verhalten überprüfen.
――Der Beobachter beobachtet das Objekt, das viele Zahlen generiert, und zeigt den Wert an.
――Die Anzeigemethode unterscheidet sich je nach Beobachter.
--DigitalObserver
zeigt den Wert numerisch an
--GraphicObserver
zeigt die Werte in einem einfachen Diagramm an
$ 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:*********************************************
Ähnlicher Code wurde in das Git-Repository hochgeladen. https://github.com/ttsubo/study_of_design_pattern/tree/master/Observer
--Verzeichnisaufbau
.
├── Main.py
└── observer
├── __init__.py
├── generator.py
└── observer.py
Die Rolle "Subjekt" repräsentiert die "beobachtete Seite". Die Rolle "Subjekt" verfügt über eine Methode zum Registrieren der Beobachterrolle "Beobachter" und eine Methode zum Löschen. Außerdem wird eine Methode zum Abrufen des aktuellen Status deklariert. Im Beispielprogramm übernimmt die Klasse "NumberGenerator" diese Rolle.
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
Die Rolle "Konkretes Subjekt" ist eine Rolle, die eine konkrete "beobachtete Seite" ausdrückt. Wenn sich der Status ändert, teilen Sie dies der registrierten "Beobachter" -Rolle mit. Im Beispielprogramm übernimmt die Klasse "RandomNumberGenerator" diese Rolle.
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()
Die Rolle des "Beobachters" ist die Rolle, durch die Rolle des "Subjekts" gesagt zu werden, dass "der Staat sich verändert hat". Die Methode dafür ist "Update". Im Beispielprogramm übernimmt die Klasse "Observer" diese Rolle.
observer/observer.py
import time
from abc import ABCMeta, abstractmethod
class Observer(metaclass=ABCMeta):
@abstractmethod
def update(self, ganerator):
pass
Die Rolle von "ConcreteObserver" ist ein konkreter "Beobachter". Wenn die Methode "update" aufgerufen wird, wird der aktuelle Status der Rolle "Subject" in dieser Methode abgerufen. Im Beispielprogramm übernehmen die Klassen "DigitObserver" und "GraphObserver" diese Rolle.
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)
Im Beispielprogramm übernimmt die Methode "startMain" diese Rolle.
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