Apprenez le modèle de conception "Builder" avec Python

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.

■ Constructeur

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 W3sDesign_Builder_Design_Pattern_UML.jpg UML class diagram 2880px-Builder_UML_class_diagram.svg-2.png (Ce qui précède est cité sur Wikipedia)

■ Exemple de programme "Builder"

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.

(1) Essayez de courir en mode 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.

(2) Essayez de déplacer le mode 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. tablehtml.png

■ Détails de l'exemple de programme

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

(1) Le rôle du constructeur

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

(2) Le rôle de Concrete Builder

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

(3) Le rôle du directeur

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

(4) Le rôle du client

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

■ URL de référence

Recommended Posts

Apprenez le modèle de conception "Builder" avec Python
Apprenez le modèle de conception "Prototype" avec Python
Apprenez le modèle de conception "Flyweight" en Python
Apprenez le modèle de conception "Observer" en Python
Apprenez le modèle de conception "Memento" avec Python
Apprenez le modèle de conception "Proxy" en Python
Apprenez le modèle de conception "Commande" en Python
Apprenez le modèle de conception "Visiteur" avec Python
Apprenez le modèle de conception "Bridge" avec Python
Apprenez le modèle de conception "Mediator" avec Python
Apprenez le modèle de conception "Décorateur" avec Python
Apprenez le modèle de conception "Iterator" avec Python
Apprenez le modèle de conception «Stratégie» avec Python
Apprenez le modèle de conception "Composite" avec Python
Apprenez le modèle de conception "État" en Python
Apprenez le modèle de conception "Adapter" avec Python
Apprenez le modèle de conception "Abstract Factory" avec Python
Apprenez le modèle de conception "Méthode de modèle" en Python
Apprenez le modèle de conception "Méthode d'usine" en Python
Apprenez le modèle de conception «Chaîne de responsabilité» en Python
Apprenez le modèle de conception "Singleton" avec Python
Apprenez le modèle de conception "Façade" avec Python
Implémenter le modèle Singleton en Python
Modèle de conception #Builder
Motif singleton en Python
Modèle de visiteur en Python
Trouver des erreurs en Python
J'ai écrit un modèle de conception dans l'édition Kotlin Builder
Modèles de conception en Python: introduction
Python Design Pattern - Méthode de modèle
Obtenir l'API arXiv en Python
Python dans le navigateur: la recommandation de Brython
Enregistrez le fichier binaire en Python
Frappez l'API Sesami en Python
Obtenez le chemin du bureau en Python
Obtenez le chemin du script en Python
Dans la commande python, python pointe vers python3.8
Accédez à l'API Web en Python
J'ai écrit la file d'attente en Python
Calculer le mois précédent en Python
Examiner la classe d'un objet avec python
Obtenez le chemin du bureau en Python
Obtenez le nom d'hôte en Python
Accéder à l'API Twitter avec Python
La première étape de Python Matplotlib
J'ai écrit la pile en Python
Maîtriser le module lowref en Python
Apprenez les bases de Python ① Débutants élémentaires
Charger le SDK Python distant avec IntelliJ
Essayez d'utiliser l'API Wunderlist en Python
Vérifiez le comportement du destroyer en Python
[Python Kivy] À propos de la modification du thème de conception
Essayez d'utiliser l'API Kraken avec Python
Apprenez les bases en touchant les variables python
Ecrire le test dans la docstring python
Prenez la somme logique de List en Python (fonction zip)
Modèle de conception du GoF à partir du problème 2. Structure
Afficher Python 3 dans le navigateur avec MAMP