En tant que matériel d'apprentissage des modèles de conception du GoF, le livre «Introduction aux modèles de conception appris dans le langage Java augmenté et révisé» semble être utile. Cependant, comme les exemples repris sont basés sur JAVA, j'ai essayé la même pratique avec Python pour approfondir ma compréhension.
Le modèle Builder (modèle de construction) est l'un des modèles de conception définis par le GoF (Gang of Four; 4 gangs). Il permet la création dynamique d'objets en faisant abstraction du processus de création d'objets. UML class and sequence diagram UML class diagram (Ce qui précède est cité sur Wikipedia)
Puisqu'il est difficile d'assembler une structure complexe à la fois avec le modèle Builder, il semble que chaque partie qui compose le tout soit créée à l'avance, et une instance avec la structure est assemblée étape par étape. En fait, je voudrais essayer d'exécuter un exemple de programme qui crée un "document" en utilisant le modèle Builder et vérifier comment cela fonctionne.
html
, un fichier HTML de liens tabulaires est généré.simple
Tout d'abord, déplaçons la sortie de code par le document au format texte brut.
$ python Main.py plain
======================
Greeting
*** From the morning to the afternoon ***
- Good morning
- Hello
*** In the evening ***
- Good evening
- Good night
- Good bye
======================
Un document appelé texte brut a été produit.
html
Ensuite, exécutons le code qui crée une page Web ** basée sur une table **.
$ python Main.py html
[Greeting.html] was created.
Un fichier appelé «Greeting.html» a été généré. Lorsque j'ai vérifié l'apparence avec un navigateur Web, cela ressemblait à ceci.
Un code similaire a été téléchargé dans le référentiel Git. https://github.com/ttsubo/study_of_design_pattern/tree/master/Builder
.
├── Main.py
└── builder
├── __init__.py
├── builder.py
├── director.py
├── htmlbuilder
│ ├── __init__.py
│ └── html_builder.py
└── textbuilder
├── __init__.py
└── text_builder.py
Le rôle Builder
définit l'interface de création d'une instance.
Le rôle Builder
fournit des méthodes pour créer chaque partie de l'instance.
Dans l'exemple de programme, la classe Builder
remplit ce rôle.
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
Le rôle ConcreteBuilder
est une classe qui implémente l'interface pour le rôle Builder
. La méthode appelée dans l'instanciation réelle est définie ici. Il fournit également une méthode pour obtenir le résultat final.
Dans l'exemple de programme, la classe TextBuilder
et la classe HTMLBuilder
remplissent ce rôle.
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
Le rôle Director
crée une instance en utilisant l'interface de rôle Builder
.
Il ne repose pas sur le rôle ConcreteBuilder
. N'utilisez que les méthodes du rôle ** Builder
** pour que cela fonctionne correctement quel que soit le rôle ConcreteBuilder
.
Dans l'exemple de programme, la classe Director
remplit ce rôle.
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()
C'est un rôle qui utilise le rôle de «Builder».
Dans l'exemple de programme, la méthode startMain
remplit ce rôle.
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