Ich habe Designmuster geübt, um Code zu schreiben, der sich des Designs bewusst war. Andere Entwurfsmuster werden häufig veröffentlicht.
Das Hauptziel ist zu verstehen, wann, was und wie Entwurfsmuster verwendet werden. (Ich bin neu in Java oder einer statisch typisierten Sprache und habe keine lange Geschichte mit Python. Ich denke, es gibt einige Dinge, die Pythonista nicht ähneln. Wenn Sie Vorschläge haben, bringen Sie mir dies bitte bei.)
Diesmal ist das Muster Beobachter bezüglich des Verhaltens.
Im Beobachtermuster wird der Beobachter benachrichtigt, wenn sich der Zustand des Beobachtungsziels ändert. Das Observer-Muster ist nützlich, wenn Sie die Verarbeitung beschreiben, die auf Statusänderungen reagiert.
Mit dem hier erstellten Beispielprogramm kann der Beobachter ein Objekt beobachten, das eine große Zahl generiert, und seinen Wert anzeigen. Die Anzeigemethode unterscheidet sich jedoch je nach Beobachter. DigitObserver zeigt die Werte numerisch an, während GraphObserver die Werte in einem einfachen Diagramm anzeigt.
observer.py
from abc import ABCMeta, abstractmethod
class Observer(Exception):
__meta__ = ABCMeta
@abstractmethod
def update(self, generator):
pass
Die Beobachterschnittstelle ist eine Schnittstelle, die einen "Beobachter" ausdrückt. Bestimmte Beobachter implementieren diese Schnittstelle.
Es ist der NumberGenerator, der die Nummer generiert, die die Aktualisierungsmethode aufruft.
Die Aktualisierungsmethode ist eine Methode, mit der NumberGenerator dem Beobachter mitteilt, dass "Mein Inhalt aktualisiert wurde. Bitte aktualisieren Sie auch die Anzeige."
number_generator.py
from abc import ABCMeta, abstractmethod
class NumberGenerator(metaclass=ABCMeta):
__observers = []
def add_observer(self, observer):
self.__observers.append(observer)
def delete_observer(self, observer):
self.__observers.remove(observer)
def notify_observers(self):
for observer in self.__observers:
observer.update(self)
@abstractmethod
def get_number():
pass
@abstractmethod
def execute():
pass
Die NumberGenerator-Klasse ist eine abstrakte Klasse, die Zahlen generiert. Die eigentliche Zahlengenerierung (Ausführungsmethode) und der Teil zum Abrufen der Zahl (Methode get_number) sind abstrakte Methoden, die voraussichtlich von der Unterklasse implementiert werden.
Das Beobachterfeld ist das Feld, in dem die Beobachter gespeichert sind, die den Zahlengenerator beobachten.
add_observer ist eine Methode zum Hinzufügen eines Beobachters, und delete_observer ist eine Methode zum Löschen eines Beobachters.
Die Methode notify_observers teilt allen Beobachtern mit: "Mein Inhalt wurde aktualisiert. Bitte aktualisieren Sie Ihre Anzeige." Bei dieser Methode wird die Aktualisierungsmethode für jeden Beobachter in den Beobachtern aufgerufen.
random_number_generator.py
import random
from number_generator import NumberGenerator
class RandomNumberGenerator(NumberGenerator):
__number = 0
def __init__(self):
self.__rand = random
def get_number(self):
return self.__number
def execute(self):
for i in range(0, 20):
self.__number = self.__rand.randint(0, 50)
self.notify_observers()
Die RandomNumberGenerator-Klasse ist eine Unterklasse von NumberGenerator, die Zufallszahlen generiert.
Das Zufallsfeld enthält den Zufallszahlengenerator und das Zahlenfeld enthält den aktuellen Zufallswert.
Die Methode get_number gibt den Wert des Zahlenfelds zurück.
Die Methode execute generiert 20 Zufallszahlen (Ganzzahlen von 0 bis 49) und verwendet jedes Mal notify_observers, um den Beobachter zu benachrichtigen.
digit_observer.py
import time
import logging
from observer import Observer
class DigitObserver(Observer):
def update(self, generator):
print('DigitObserver:' + str(generator.get_number()))
try:
time.sleep(1)
except InterruptedError as e:
logging.exception(e)
Die DigitObserver-Klasse ist eine Klasse, die die Beobachterschnittstelle implementiert und verwendet wird, um die Anzahl der Beobachtungen als "Zahl" anzuzeigen. Verwenden Sie die Methode get_number von NumberGenerator, die in der Aktualisierungsmethode als Argument angegeben ist, um die Nummer abzurufen und anzuzeigen. Es gibt Intervalle, in denen Sie sehen können, wie die Anzeige aussieht.
graph_observer.py
import sys
import time
from observer import Observer
class GraphObserver(Observer):
def update(self, generator):
sys.stdout.write('GraphObserver:')
count = generator.get_number()
for i in range(0, count):
sys.stdout.write('*')
print('')
try:
time.sleep(1)
except InterruptedError:
pass
Die GraphObserver-Klasse ist auch eine Klasse, die die Observer-Schnittstelle implementiert. Diese Klasse repräsentiert die Anzahl der Beobachtungen in einem "einfachen Graphen" wie *****.
main.py
from digit_observer import DigitObserver
from graph_observer import GraphObserver
from random_number_generator import RandomNumberGenerator
def main():
generator = RandomNumberGenerator()
observer1 = DigitObserver()
observer2 = GraphObserver()
generator.add_observer(observer1)
generator.add_observer(observer2)
generator.execute()
if __name__ == "__main__":
main()
Erstellen Sie eine Instanz von RandomNumberGenerator und zwei Beobachter davon. Observer1 ist eine Instanz von DigitObserver und Observer2 ist eine Instanz von GraphObserver.
Verwenden Sie nach der Registrierung des Beobachters mit der Methode add_observer generator.execute, um die Nummer zu generieren.
Ausführungsergebnis
DigitObserver:17
GraphObserver:*****************
DigitObserver:43
GraphObserver:*******************************************
DigitObserver:47
GraphObserver:***********************************************
DigitObserver:34
GraphObserver:**********************************
DigitObserver:30
GraphObserver:******************************
DigitObserver:50
GraphObserver:**************************************************
DigitObserver:7
GraphObserver:*******
DigitObserver:40
GraphObserver:****************************************
DigitObserver:39
GraphObserver:***************************************
DigitObserver:41
GraphObserver:*****************************************
DigitObserver:38
GraphObserver:**************************************
DigitObserver:3
GraphObserver:***
DigitObserver:22
GraphObserver:**********************
DigitObserver:26
GraphObserver:**************************
DigitObserver:0
GraphObserver:
DigitObserver:23
GraphObserver:***********************
Ein Objekt wurde überwacht, indem eine Methode hinzugefügt wurde, die das andere Objekt (Beobachter) registriert. Das überwachte Objekt sendet eine Nachricht an den registrierten Beobachter, wenn es sich ändert.
Wie der Beobachter mit diesen Informationen umgeht, ist für das überwachte Objekt irrelevant und kann eine beliebige Objektklasse sein.
Objekte verstehen den Grund nicht unbedingt, und infolgedessen kann die Abhängigkeit zwischen Objekten verringert werden, und der Beobachter verwaltet das Benachrichtigungsziel so, dass das Beobachtungsziel die Benachrichtigungsseite nicht kennen muss.
Recommended Posts