Ich übte Designmuster, 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 bezog sich das Muster Dekorateur auf die Struktur.
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.
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.|*||/
/||*+- - - - - -+*||/
/|+- - - - - - - - - -+|/
/+- - - - - - - - - - - -+/
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
Recommended Posts