[GO] Lernen Sie das Entwurfsmuster "Proxy" in Python

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.

■ Proxy (Proxy-Muster)

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 W3sDesign_Proxy_Design_Pattern_UML.jpg UML class diagram proxy.png (Das Obige ist aus Wikipedia zitiert)

■ Beispielprogramm "Proxy"

Eigentlich möchte ich ein Beispielprogramm ausführen, das das Proxy-Muster verwendet, und das folgende Verhalten überprüfen.

(1) Behandeln Sie den aktuellen Druckeragenten als Druckerbenutzer (2) Zeigen Sie den Namen des Druckerbenutzers an, indem Sie ihn vorher und nachher in "===" einfügen. (3) Zeigen Sie die Zeichenfolge an.
$ 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.

■ Details zum Beispielprogramm

Ä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

(1) Rolle des Subjekts

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

(2) Rolle des Vertreters

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)

(3) Die Rolle des realen Subjekts

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')

(4) Die Rolle des Kunden

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()

■ Referenz-URL

  • [Nach "Einführung in in Java-Sprache erlernte Entwurfsmuster" (nicht)](https://medium.com/since-i-want-to-start-blog-that-looks-like-men-do/java Einführung in Entwurfsmuster, die in Sprachen gelernt wurden - Finishing-Not-2cc9b34a30b2)
  • [Qiita-Artikel "Design Pattern #Proxy" (https://qiita.com/nirperm/items/cb200058edb935adb26c)

Recommended Posts