[PYTHON] Entwurfsmuster #Decorator

Ich übte Designmuster, um Code zu schreiben, der sich des Designs bewusst war. Andere Entwurfsmuster werden häufig veröffentlicht.

Vorwort

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 bezog sich das Muster Dekorateur auf die Struktur.

Was ist Dekorateur?

Durch Abdecken eines vorhandenen Objekts mit einem neuen Decorator-Objekt unter Beibehaltung einer transparenten Schnittstelle (API) können Funktionen von außen hinzugefügt oder neu geschrieben werden, ohne den Inhalt vorhandener Funktionen und Klassen direkt zu berühren. Es wird auch als Alternative zur Klassenvererbung verwendet, wenn eine vorhandene Klasse erweitert wird.

Das hier erstellte Beispielprogramm besteht darin, einen dekorativen Rahmen um die Zeichenfolge anzuzeigen. Der dekorative Rahmen hier ist mit den Zeichen-, +, | geschrieben.

Gesamtklassendiagramm

Decorator

display.py


from abc import ABCMeta, abstractmethod


class Display(metaclass=ABCMeta):

    @abstractmethod
    def get_columns(self):
        pass

    @abstractmethod
    def get_rows(self):
        pass

    @abstractmethod
    def get_row_text(self):
        pass

    def show(self):
        for i in range(self.get_rows()):
            print(self.get_row_text(i))

Die Display-Klasse ist eine abstrakte Klasse, die eine mehrzeilige Zeichenfolge anzeigt.

Da get_columns, get_rows und get_row_text abstrakte Methoden sind, bleibt nur die Deklaration der Unterklasse überlassen. Jede Rolle ist get_columns ist die Anzahl der horizontalen Zeichen, get_rows ist die Anzahl der vertikalen Zeilen und get_row_text ist eine Methode zum Abrufen der Zeichenfolge der angegebenen Zeile.

Die Show ist ein Muster der Vorlagenmethode, das die abstrakten Methoden get_rows und get_row_text verwendet. Es ist eine Methode, um die Zeichenfolge abzurufen, die von get_rows und get_row_text angezeigt werden soll, und um alle Zeilen in der for-Schleife anzuzeigen.

string_display.py



from display import Display


class StringDisplay(Display):

    def __init__(self, string):
        self.__string = string

    def get_columns(self):
        return len(self.__string)

    def get_rows(self):
        return 1

    def get_row_text(self, row):
        if row == 0:
            return self.__string
        else:
            return None

Die StringDisplay-Klasse ist eine Klasse, die eine einzelne Textzeile anzeigt und eine Unterklasse der Display-Klasse ist. Es implementiert die in der Display-Klasse deklarierte abstrakte Methode. Das Zeichenfolgenfeld enthält die anzuzeigende Zeichenfolge. Die StringDisplay-Klasse zeigt nur eine Zeile mit dem Inhalt des Zeichenfolgenfelds an, sodass get_columns die Länge der Zeichenfolge und get_rows 1 zurückgibt. get_row_text gibt ein Zeichenfolgenfeld nur zurück, wenn es den Wert in Zeile 0 annimmt.

border.py


from abc import ABCMeta
from display import Display


class Border(Display):

    __metaclass__ = ABCMeta

    def _border(self, display):
        self._display = display

Die Border-Klasse ist eine abstrakte Klasse, die einen "dekorativen Rahmen" darstellt. Es ist jedoch als Unterklasse der Display-Klasse definiert, die Zeichenfolgen anzeigt. Mit anderen Worten, durch Vererbung ** hat der Frame die gleiche Methode wie der Inhalt **. Die Border-Klasse erbt die Methoden get_columns, get_rows, get_row_text und show.

side_border.py


from border import Border


class SideBorder(Border):

    def __init__(self, display, ch):
        self.display = display
        self.__border_char = ch

    def get_columns(self):
        return 1 + self.display.get_columns() + 1

    def get_rows(self):
        return self.display.get_rows()

    def get_row_text(self, row):
        return self.__border_char + \
            self.display.get_row_text(row) + \
            self.__border_char

Die SideBorder-Klasse ist eine Art konkreter dekorativer Rahmen und eine Unterklasse der Border-Klasse. Die SideBorder-Klasse verziert die linke und rechte Seite der Zeichenfolge mit festen Zeichen (borderChar). Und alle in der Oberklasse deklarierten abstrakten Methoden sind hier implementiert.

get_columns ist eine Methode, um die Anzahl der Zeichen neben den angezeigten Zeichen abzurufen. Die Anzahl der Zeichen ist die Anzahl der Zeichen im "Inhalt", die um diesen dekorativen Rahmen gewickelt sind, sowie die linken und rechten dekorativen Zeichen.

Da die SideBorder-Klasse die vertikale Richtung nicht ändert, ist display.get_rows der Rückgabewert der Methode get_rows.

Die Methode get_row_text ruft die Zeichenfolge der durch das Argument angegebenen Zeile ab. Der Rückgabewert ist display.get_row_text (Zeile), wobei das dekorative Zeichen bodrder_char zu beiden Seiten der Inhaltszeichenfolge hinzugefügt wird.

full_border.py


from border import Border


class FullBorder(Border):

    def __init__(self, display):
        self.display = display

    def get_columns(self):
        return 1 + self.display.get_columns() + 1

    def get_rows(self):
        return 1 + self.display.get_rows() + 1

    def get_row_text(self, row):
        if row == 0:
            return '+' + self._make_line('-', self.display.get_columns()) + '+'
        elif row == self.display.get_rows() + 1:
            return '+' + self._make_line('-', self.display.get_columns()) + '+'
        else:
            return '|' + self.display.get_row_text(row - 1) + '|'

    def _make_line(self, ch, count):
        buf = []
        for i in range(0, count):
            buf.append(ch)
        return ' '.join(buf)

Die FullBorder-Klasse ist wie die SideBorder-Klasse eine der Border-Unterklassen. Die FullBorder-Klasse ist oben, unten, links und rechts dekoriert.

Die Methode make_line ist eine Hilfsmethode, die eine Zeichenfolge aus aufeinanderfolgenden angegebenen Zeichen erstellt.

main.py


from string_display import StringDisplay
from side_border import SideBorder
from full_border import FullBorder


def main():
    b1 = StringDisplay('Hello, world')
    b2 = SideBorder(b1, '#')
    b3 = FullBorder(b2)
    b4 = SideBorder(
        FullBorder(
            FullBorder(
                SideBorder(
                    FullBorder(
                        StringDisplay('Hallo.')
                    ), '*'
                )
            )
        ), '/'
    )

    b1.show()
    b2.show()
    b3.show()
    b4.show()

if __name__ == "__main__":
    main()

Ausführungsergebnis (obwohl die Form verzerrt ist ...)

Hello, world
#Hello, world#
+- - - - - - - - - - - - - -+
|#Hello, world#|
+- - - - - - - - - - - - - -+
/+- - - - - - - - - - - -+/
/|+- - - - - - - - - -+|/
/||*+- - - - - -+*||/
/||*|Hallo.|*||/
/||*+- - - - - -+*||/
/|+- - - - - - - - - -+|/
/+- - - - - - - - - - - -+/

Zusammenfassung

Im Dekorationsmuster werden der dekorative Rahmen und der Inhalt gleichgesetzt.

Im Beispielprogramm wird die Identifikation ausgedrückt, wenn die Randklasse, die den dekorativen Rahmen darstellt, eine Unterklasse der Anzeigeklasse ist, die den Inhalt darstellt. Mit anderen Worten, die Border-Klasse (Unterklassen der Border-Klasse) hat dieselbe Schnittstelle wie die Display-Klasse, die den Inhalt darstellt.

Selbst wenn Sie einen Frame zum Umschließen des Inhalts verwenden, wird die Schnittstelle nicht ausgeblendet, sodass die Methoden get_columns, get_rows, get_row_text, show von anderen Klassen aus gesehen werden können. Dies ist, was die Schnittstelle "transparent" genannt wird.

Je mehr Sie das Decorator-Muster einwickeln, desto mehr Funktionen werden hinzugefügt. ** Ich konnte Funktionen hinzufügen, ohne die Verpackung zu ändern. ** ** **

Python hat in erster Linie Dekoratoren

Referenz

Recommended Posts

Entwurfsmuster #Decorator
Entwurfsmuster #Builder
Entwurfsmuster #Adapter
Entwurfsmuster #Observer
Entwurfsmuster #Facade
Entwurfsmuster #Strategie
Entwurfsmuster #Singleton
Entwurfsmuster #Proxy
Lernen Sie das Designmuster "Decorator" mit Python
Entwurfsmuster #Factory-Methode
Dekorationsmuster in Java
Entwurfsmuster # Template-Methode
Dekorateur 1
Dekorateur 2
Oreore-Entwurfsmuster: Glokale Variable
Dekorateur
Dekorateur
Python Design Pattern - Template-Methode
[Viererbande] Designmuster lernen
Grobe Zusammenfassung des GoF-Java-Entwurfsmusters
Lernen Sie das Entwurfsmuster "Prototype" mit Python
Lernen Sie das Entwurfsmuster "Builder" mit Python
[Viererbande] Design Pattern Learning - Singleton
[Viererbande] Designmuster lernen --Besucher
Design Muster-Adapter
[Viererbande] Design Pattern Learning - Vermittler
Lernen Sie das Designmuster "Flyweight" in Python
Lernen Sie das Entwurfsmuster "Observer" in Python
Lernen Sie das Entwurfsmuster "Memento" mit Python
Lernen Sie das Entwurfsmuster "Proxy" in Python
Lernen Sie das Entwurfsmuster "Befehl" in Python
[Viererbande] Designmusterlernen --Iterator
MyHDL Dekorateur
GoF-Entwurfsmuster aus dem Problem 2. Struktur
Lernen Sie das Entwurfsmuster "Besucher" mit Python
Lernen Sie das Entwurfsmuster "Bridge" mit Python
Lernen Sie das Entwurfsmuster "Mediator" mit Python
Design Muster-Iterator
[Viererbande] Designmuster lernen - Fassade
[Viererbande] Design Pattern Learning - Composite
[Viererbande] Designmuster lernen - Prototyp
GoF-Entwurfsmuster aus dem Problem 1. Generation
Lernen Sie das Entwurfsmuster "Iterator" mit Python
[Viererbande] Designmuster lernen - Andenken
[Viererbande] Designmuster lernen - Staat
[Vierergruppe] Design Pattern Learning - Interpreter
[Viererbande] Design Pattern Learning - Builder
Lernen Sie das Entwurfsmuster "Strategie" mit Python
[Viererbande] Designmuster lernen - Brücke
Lernen Sie das Entwurfsmuster "Composite" mit Python
Lernen Sie das Entwurfsmuster "Singleton" mit Python
Lernen Sie das Entwurfsmuster "State" in Python
Lernen Sie das Entwurfsmuster "Adapter" mit Python
[Viererbande] Designmuster lernen --Proxy
[Viererbande] Design Pattern Learning - Strategie
[Viererbande] Designmuster lernen --Adapter
Lernen Sie das Designmuster "Facade" mit Python
[Viererbande] Design Pattern Learning - Beobachter
[Viererbande] Designmuster lernen - Befehl
GoF-Entwurfsmuster aus dem Problem 3. Verhalten
[Viererbande] Designmuster lernen - Fluggewicht