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 Builder-Muster (Builder-Muster) ist eines der von GoF (Gang of Four; 4 Banden) definierten Entwurfsmuster. Es ermöglicht die dynamische Objekterstellung durch Abstraktion des Objekterstellungsprozesses. UML class and sequence diagram UML class diagram (Das Obige wird aus Wikipedia zitiert)
Da es schwierig ist, eine komplexe Struktur mit dem Builder-Muster auf einmal zusammenzusetzen, wird anscheinend jeder Teil, aus dem das Ganze besteht, im Voraus erstellt und eine Instanz mit der Struktur wird Schritt für Schritt zusammengesetzt. Eigentlich möchte ich versuchen, ein Beispielprogramm auszuführen, das ein "Dokument" mit dem Builder-Muster erstellt, und überprüfen, wie es funktioniert.
--Wenn im Nur-Modus betrieben, wird ein Dokument im Nur-Text-Format ausgegeben. --Wenn im HTML-Modus gearbeitet, wird eine HTML-Datei mit tabellarischen Links generiert.
Verschieben wir zunächst den vom Dokument im Nur-Text-Format ausgegebenen Code.
$ python Main.py plain
======================
Greeting
*** From the morning to the afternoon ***
- Good morning
- Hello
*** In the evening ***
- Good evening
- Good night
- Good bye
======================
Es wurde ein sogenanntes Nur-Text-Dokument ausgegeben.
Lassen Sie uns als Nächstes den Code ausführen, der eine ** tabellenbasierte ** Webseite erstellt.
$ python Main.py html
[Greeting.html] was created.
Eine Datei mit dem Namen "Greeting.html" wurde generiert. Als ich das Erscheinungsbild mit einem Webbrowser überprüfte, sah es so aus.
Ähnlicher Code wurde in das Git-Repository hochgeladen. https://github.com/ttsubo/study_of_design_pattern/tree/master/Builder
--Verzeichnisaufbau
.
├── Main.py
└── builder
├── __init__.py
├── builder.py
├── director.py
├── htmlbuilder
│ ├── __init__.py
│ └── html_builder.py
└── textbuilder
├── __init__.py
└── text_builder.py
Die Rolle "Builder" definiert die Schnittstelle zum Erstellen einer Instanz. Die Rolle "Builder" bietet Methoden zum Erstellen jedes Teils der Instanz. Im Beispielprogramm übernimmt die Builder-Klasse diese Rolle.
builder/builder.py
from abc import ABCMeta, abstractmethod
class Builder(metaclass=ABCMeta):
@abstractmethod
def makeTitle(self, title):
pass
@abstractmethod
def makeString(self, str):
pass
@abstractmethod
def makeItems(self, items):
pass
@abstractmethod
def close(self):
pass
Die Rolle "ConcreteBuilder" ist eine Klasse, die die Schnittstelle für die Rolle "Builder" implementiert. Hier wird die in der eigentlichen Instanziierung aufgerufene Methode definiert. Es bietet auch eine Methode, um das Endergebnis zu erhalten. Im Beispielprogramm übernehmen die Klasse "TextBuilder" und die Klasse "HTMLBuilder" diese Rolle.
builder/text_builder.py
from builder.builder import Builder
class TextBuilder(Builder):
def __init__(self):
self.buffer = []
def makeTitle(self, title):
self.buffer.append("======================\n")
self.buffer.append(title + "\n")
self.buffer.append("\n")
def makeString(self, str):
self.buffer.append("*** " + str + " ***" + "\n")
def makeItems(self, items):
for i in items:
self.buffer.append("- " + i + "\n")
def close(self):
self.buffer.append("======================\n")
def getResult(self):
return ''.join(self.buffer)
builder/html_builder.py
from builder.builder import Builder
class HTMLBuilder(Builder):
def __init__(self):
self.buffer = []
self.filename = ""
self.f = None
self.makeTitleCalled = False
def makeTitle(self, title):
self.filename = title+".html"
self.f = open(self.filename, "w")
self.f.write("<html><head><title>"+title+"</title></head></html>")
self.f.write("<h1>"+title+"</h1>")
self.makeTitleCalled = True
def makeString(self, str):
if not self.makeTitleCalled:
raise RuntimeError
self.f.write("<p>"+str+"</p>")
def makeItems(self, items):
if not self.makeTitleCalled:
raise RuntimeError
self.f.write("<ul>")
for i in items:
self.f.write("<li>"+i+"</li>")
self.f.write("</ul>")
def close(self):
if not self.makeTitleCalled:
raise RuntimeError
self.f.write("</body></html>")
self.f.close()
def getResult(self):
return self.filename
Die Rolle "Director" erstellt eine Instanz über die Rollenschnittstelle "Builder". Es basiert nicht auf der Rolle "ConcreteBuilder". Verwenden Sie nur die Methoden der Rolle "Builder", damit sie unabhängig von der Rolle "ConcreteBuilder" einwandfrei funktioniert. Im Beispielprogramm übernimmt die Klasse "Director" diese Rolle.
builder/director.py
class Director(object):
def __init__(self, builder):
self.__builder = builder
def construct(self):
self.__builder.makeTitle("Greeting")
self.__builder.makeString("From the morning to the afternoon")
self.__builder.makeItems(["Good morning", "Hello"])
self.__builder.makeString("In the evening")
self.__builder.makeItems(["Good evening", "Good night", "Good bye"])
self.__builder.close()
Es ist eine Rolle, die die Rolle des Builders verwendet. Im Beispielprogramm übernimmt die Methode "startMain" diese Rolle.
Main.py
import sys
from builder.director import Director
from builder.textbuilder.text_builder import TextBuilder
from builder.htmlbuilder.html_builder import HTMLBuilder
def startMain(opt):
if opt == "plain":
builder = TextBuilder()
director = Director(builder)
director.construct()
result = builder.getResult()
print(result)
elif opt == "html":
builder = HTMLBuilder()
director = Director(builder)
director.construct()
result = builder.getResult()
print("[" + result + "]" + " was created.")
if __name__ == "__main__":
startMain(sys.argv[1])
Recommended Posts