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.)
Dieses Mal bezog sich das Muster Proxy auf die Struktur.
Bereiten Sie einen Proxy vor, um die Erstellung von Instanzen und Zugriffsbeschränkungen zu steuern, und lassen Sie den Proxy die Arbeit ausführen, bis sie benötigt wird. Wenn der Agent jedoch den möglichen Bereich überschreitet, gibt der Agent der ursprünglichen Person die Rolle.
Dieses Beispielprogramm ist ein "benannter Drucker". Die Hauptklasse erstellt eine Klasseninstanz (Agent) für PrinterProxy. Nennen Sie die Instanz "Alice" und zeigen Sie den Namen an. Benennen Sie es dann in "Bob" um und zeigen Sie diesen Namen an.
Durch Festlegen oder Abrufen des Namens haben wir noch keine Instanz (Person) der realen Druckerklasse erstellt. Die PrinterProxy-Klasse übernimmt das Festlegen und Abrufen des Namens. Schließlich erstellt die PrinterProxy-Klasse nur dann eine Instanz der Printer-Klasse, wenn es Zeit ist, die my_print-Methode tatsächlich aufzurufen und tatsächlich zu drucken.
Eine Schnittstelle namens Printable ist definiert, um die PrinterProxy-Klasse mit der Printer-Klasse gleichzusetzen. Hier wird das Beispielprogramm unter der Annahme erstellt, dass das Instanziieren der Druckerklasse lange dauert. Um auszudrücken, dass es einige Zeit dauert, rufe ich vom Konstruktor eine Methode namens heavy_job auf und verdiene einige Sekunden als "schwere Verarbeitung".
printer.py
import sys
import time
from printable import Printable
class Printer(Printable):
def __init__(self, name):
self.__name = name
self.__heavy_job('Druckerinstanz({0})Wird generiert'.format(self.__name))
def set_printer_name(self, name):
self.__name = name
def get_printer_name(self):
return self.__name
def my_print(self, string):
print('===' + ' ' + self.__name + ' ' + '===')
print(string)
def __heavy_job(self, msg):
sys.stdout.write(msg)
for i in range(1, 5):
try:
time.sleep(1)
except InterruptedError:
pass
sys.stdout.write('.')
print('Erledigt.')
Die Druckerklasse ist eine Klasse, die "die Person" darstellt. Ich mache Heavy_job als "Heavy Job".
Danach gibt es set_printer_name zum Festlegen des Namens, get_printer_name zum Abrufen des Namens und my_print zum Anzeigen der Zeichenfolge. Das Zentrum des Proxy-Musters befindet sich in Richtung der PrinterProxy-Klasse.
printable.py
from abc import abstractmethod
class Printable():
@abstractmethod
def set_printer_name(self, name):
pass
@abstractmethod
def get_printer_name(self):
pass
@abstractmethod
def my_printer(self, string):
pass
Die druckbare Oberfläche dient zum Gleichsetzen der PrinterProxy-Klasse mit der Printer-Klasse.
printer_proxy.py
from printable import Printable
from printer import Printer
class PrinterProxy(Printable):
def __init__(self, name):
self.__name = name
self.__real = None
def set_printer_name(self, name):
if (self.__real is not None):
self.__real.set_printer_name(name)
self.__name = name
def get_printer_name(self):
return self.__name
def my_print(self, string):
self.__realize()
self.__real.my_print(string)
def __realize(self):
if (self.__real is None):
self.__real = Printer(self.__name)
Die PrinterProxy-Klasse fungiert als Agent. Implementiert die druckbare Oberfläche. Das Namensfeld dient zum Halten des Namens und das reale Feld zum Halten der "Person".
Legen Sie im Konstruktor den Namen fest. Die Methode set_printer_name legt einen neuen Namen fest. Wenn real nicht None ist, legen Sie auch den Namen für die Person fest. Wenn real jedoch None ist, wird ein Wert im Feld PrinterProxy name zurückgegeben.
Da die my_print-Methode ein Prozess außerhalb des Bereichs dieses Agenten ist, rufen Sie die Realisierungsmethode auf, um die "Person" zu generieren. Nach dem Ausführen der Realisierungsmethode enthält das reale Feld die Person. Rufen Sie also real.print auf. Dies ist "Delegation".
** Unabhängig davon, wie oft Sie set_printer_name oder get_printer_name aufrufen, wird der Drucker nicht instanziiert. Es wird keine Druckerinstanz erstellt. ** Eine Druckerinstanz wird nur erstellt, wenn die "Person" benötigt wird. (PrinterProxy-Benutzer wissen überhaupt nicht, ob die Person generiert wurde, und es besteht kein Grund zur Sorge.)
Die Realisierungsmethode erstellt eine Instanz von Printer, wenn das reale Feld None ist. Wenn das reale Feld nicht None ist, tun Sie nichts.
main.py
from printer_proxy import PrinterProxy
def main():
pp = PrinterProxy('Alice')
print('Der Name ist jetzt' + pp.get_printer_name() + 'ist.')
pp.set_printer_name('Bob')
print('Der Name ist jetzt' + pp.get_printer_name() + 'ist.')
pp.my_print('Hello, world.')
if __name__ == '__main__':
main()
Ausführungsergebnis
Der Name ist jetzt Alice.
Der Name ist jetzt Bob.
Druckerinstanz(Bob)Wird generiert....Erledigt.
=== Bob ===
Hello, world.
Im Proxy-Muster fungiert die Proxy-Rolle als Agent und übernimmt die Verarbeitung so weit wie möglich. Im Beispielprogramm war es mithilfe der Proxy-Rolle möglich, die Verarbeitung (Instanziierung) bis zum eigentlichen my_print zu verzögern.
Wenn es viele Funktionen gibt, deren Initialisierung in der tatsächlichen Nutzungsszene lange dauert, werden sie meiner Meinung nach nur dann initialisiert, wenn es Zeit ist, diese Funktionen tatsächlich zu verwenden. Ich denke, es ist eines der am häufigsten verwendeten Designmuster.
Recommended Posts