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 Proxy-Muster ist eine Art Entwurfsmuster bei der Programmierung. Ein Proxy ist im Großen und Ganzen eine Klasse, die als Schnittstelle zu etwas anderem fungiert. Die "andere Sache" kann alles sein, wie eine Netzwerkverbindung, ein großes Objekt im Speicher oder eine Ressource, die teuer oder unmöglich zu duplizieren ist. Ein bekanntes Beispiel für das Proxy-Muster ist ein Zeigerobjekt mit einem Referenzzähler. In Situationen, in denen mehrere Kopien eines komplexen Objekts erforderlich sind, kann das Hinzufügen eines Flyweight-Musters zum Proxy-Muster die Speichernutzung verringern. Normalerweise wird nur ein komplexes Objekt erstellt und es werden mehrere Proxy-Objekte erstellt. Diese Proxy-Objekte enthalten nur Verweise auf komplexe Objekte. Operationen auf dem Proxy werden an das ursprüngliche Objekt weitergeleitet. Wenn alle Proxy-Objekte zerstört sind, wird auch der von dem referenzierten komplexen Objekt verwendete Speicher freigegeben.
UML class and sequence diagram UML class diagram (Das Obige ist aus Wikipedia zitiert)
Eigentlich möchte ich ein Beispielprogramm ausführen, das das Proxy-Muster verwendet, und das folgende Verhalten überprüfen.
$ python Main.py
Der Name des Druckeragenten lautet jetzt(Alice)ist
Druckerinstanz(Alice)Wird erstellt..........Erledigt
===Druckerbenutzer(Alice) ===
Nice to meet you
Der Name des Druckeragenten lautet jetzt(Bob)ist
===Druckerbenutzer(Bob) ===
Hello, World
Der hier zu überprüfende Punkt ist, dass die Druckerinstanz (xxx) erstellt wird .......... Done "</ font> wird nur einmal angezeigt. Es ist ein Punkt. Im eigentlichen Beispielprogramm wird Singleton-Muster verwendet, sodass eine Instanz eines komplexen Objekts nur einmal erstellt werden kann.
Ähnlicher Code wurde in das Git-Repository hochgeladen. https://github.com/ttsubo/study_of_design_pattern/tree/master/Proxy
--Verzeichnisaufbau
.
├── Main.py
└── proxy
├── __init__.py
└── printer_proxy.py
Definiert eine Schnittstelle zum Gleichsetzen der Rollen "Proxy" und "RealSubject". Dank der Rolle "Betreff" muss sich die Rolle "Client" des Unterschieds zwischen der Rolle "Proxy" und der Rolle "RealProxy" nicht bewusst sein. Im Beispielprogramm übernimmt die Klasse "Printable" diese Rolle.
proxy/printer_proxy.py
class Printable(metaclass=ABCMeta):
@abstractmethod
def setPrinterName(self, name):
pass
@abstractmethod
def getPrinterName(self):
pass
@abstractmethod
def myPrint(self, string):
pass
Die Rolle "Proxy" verarbeitet Anfragen von der Rolle "Client" so weit wie möglich. Wenn Sie nicht alleine damit umgehen können, überlässt die Rolle "Proxy" den Job der Rolle "RealSubject". Die Rolle "Proxy" generiert die Rolle "RealSubject", nachdem Sie die Rolle "RealSubject" wirklich benötigen. Die Rolle "Proxy" implementiert die Schnittstelle, die durch die Rolle "Betreff" definiert ist. Im Beispielprogramm übernimmt die Klasse "PrinterProxy" diese Rolle.
proxy/printer_proxy.py
class PrinterProxy(Printable):
def __init__(self, name):
self.__name = name
self.__real = None
def setPrinterName(self, name):
self.__name = name
def getPrinterName(self):
return self.__name
def myPrint(self, string):
self.__real = Printer.getPrinter(self.__name)
self.__real.myPrint(string)
Die Rolle des "realen Subjekts" des "Auftraggebers" erscheint, wenn die Rolle des "Vertreters" des "Agenten" außer Kontrolle gerät. Wie die Rolle "Proxy" implementiert auch diese Rolle die Schnittstelle, die durch die Rolle "Betreff" definiert ist. Im Beispielprogramm übernimmt die Klasse "Drucker" diese Rolle.
proxy/printer_proxy.py
class Printer(Printable):
@classmethod
def getPrinter(cls, name):
if not hasattr(cls, "_instance"):
cls._instance = cls(name)
else:
cls._instance.__name = name
return cls._instance
def __init__(self, name):
self.__name = name
self.__heavyJob('Druckerinstanz({})Wird erstellt'.format(self.__name))
def setPrinterName(self, name):
self.__name = name
def getPrinterName(self):
return self.__name
def myPrint(self, string):
print('===Druckerbenutzer({}) ==='.format(self.__name))
print(string)
print("")
def __heavyJob(self, msg):
print(msg, end='')
for _ in range(10):
time.sleep(1)
print('.', end='')
print('Erledigt')
Es ist eine Rolle, die die Rolle von "Proxy" verwendet. Im Beispielprogramm übernimmt die Methode "startMain" diese Rolle.
Main.py
from proxy.printer_proxy import PrinterProxy
def startMain():
p = PrinterProxy("Alice")
print("Der Name des Druckeragenten lautet jetzt({})ist".format(p.getPrinterName()))
p.myPrint("Nice to meet you")
p.setPrinterName("Bob")
print("Der Name des Druckeragenten lautet jetzt({})ist".format(p.getPrinterName()))
p.myPrint("Hello, World")
if __name__ == '__main__':
startMain()
Recommended Posts