[PYTHON] Modèle de conception #Builder

J'ai pratiqué les modèles de conception afin de pouvoir écrire du code conscient du design. D'autres modèles de conception seront publiés fréquemment.

Préface

L'objectif principal est de comprendre quand, quoi et comment utiliser les modèles de conception. (Je suis nouveau en Java ou dans un langage à typage statique, et je n'ai pas une longue histoire de python, donc je pense qu'il y a des choses qui ne ressemblent pas à Pythonista. Si vous avez des suggestions, apprenez-moi s'il vous plaît.)

Cette fois, le générateur de modèles pour la génération.

Qu'est-ce que Builder

Lorsque la procédure de création d'objet est compliquée, le processus de création est encapsulé et une instance avec une structure est assemblée. De plus, en préparant divers constructeurs de motifs, il est possible de gérer la production de divers motifs, et même des combinaisons de méthodes compliquées peuvent être exécutées collectivement.

Aperçu

À titre d'exemple, créez un programme qui crée du «texte» à l'aide du modèle Builder. Le texte créé ici a la structure suivante.

La classe Builder définit des méthodes de construction de documents. La classe Director utilise ensuite cette méthode pour créer un document concret,

La classe Builder est une classe abstraite et le traitement réel n'est pas écrit. Seules les méthodes abstraites sont déclarées. C'est la sous-classe de la classe Builder qui détermine le traitement spécifique pour l'écriture.

Director peut utiliser TextBuilder pour créer des documents en texte brut et HTMLBuilder peut être utilisé pour créer des documents HTML.

Diagramme de classe global

builder.py


from abc import ABCMeta, abstractmethod


class Builder(metaclass=ABCMeta):

    @abstractmethod
    def make_title(self, title):
        pass

    @abstractmethod
    def make_string(self, string):
        pass

    @abstractmethod
    def make_items(self, items):
        pass

    @abstractmethod
    def close(self):
        pass

La classe Builder est une classe abstraite qui déclare les méthodes qui créent des "documents". make_title, make_string et make_items sont des méthodes pour construire respectivement des titres, des chaînes et des puces dans des phrases. La méthode close est la méthode qui complète le document.

director.py


class Director():

    def __init__(self, builder):
        self.__builder = builder

    def construct(self):
        self.__builder.make_title('Greeting')
        self.__builder.make_string('Du matin à midi')
        string = ['Bonjour.', 'Bonjour.']
        self.__builder.make_items(string)
        self.__builder.make_string('La nuit')
        string = ['Bonsoir.', 'bonne nuit.', 'Au revoir.']
        self.__builder.make_items(string)
        self.__builder.close()

Dans la classe Director, le document est créé à l'aide des méthodes déclarées dans la classe Builder.

L'argument du constructeur de classe Director est un type de sous-classe (classe TextBuilder ou HTMLBuilder) de la classe Builder. La classe Builder est une classe abstraite, vous ne pouvez donc pas créer d'instance. Le type de sous-classe de la classe Builder donnée détermine le format de document spécifique créé par la classe Director.

La méthode construct est une méthode de création d'un document. L'appel de cette méthode génère le document. La méthode construct utilise la méthode déclarée dans Builder.

text_builder.py


from builder import Builder


class TextBuilder(Builder):
    __buffer = []

    def make_title(self, title):
        self.__buffer.append('=' * 20)
        self.__buffer.append('[' + title + ']\n')
        self.__buffer.append('\n')

    def make_string(self, string):
        self.__buffer.append('■' + string + '\n')
        self.__buffer.append('\n')

    def make_items(self, items):
        for i in range(0, len(items)):
            self.__buffer.append('●' + items[i] + '\n')
        self.__buffer.append('\n')

    def close(self):
        self.__buffer.append('=' * 20)

    def get_result(self):
        for buffer in self.__buffer:
            print(buffer)

La classe TextBuilder est une sous-classe de la classe Builder. Créez votre document en utilisant du texte brut. Le résultat est renvoyé sous forme de chaîne.

html_builder.py


import logging
from builder import Builder


class HTMLBuilder(Builder):

    def make_title(self, title):
        self.__filename = title + '.html'

        try:
            self.__writer = open(self.__filename, mode='w')
        except IOError as e:
            logging.exception(e)

        self.__writer.write('<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>' + title + '</title></head><body>')
        self.__writer.write('<h1>' + title + '<h1>')

    def make_string(self, string):
        self.__writer.write('<h1>' + string + '</p>')

    def make_items(self, items):
        self.__writer.write('<ul>')
        for i in range(0, len(items)):
            self.__writer.write('<li>' + items[i] + '</li>')
        self.__writer.write('</ul>')

    def close(self):
        self.__writer.write('</body></html>')
        self.__writer.close()

    def get_result(self):
        return self.__filename

La classe HTMLBuilder est également une sous-classe de la classe Builder. La classe HTMLBuilder crée le document sous forme de fichier HTML. Le résultat construit est renvoyé comme nom de fichier du fichier HTML.

main.py


import sys
from text_builder import TextBuilder
from html_builder import HTMLBuilder
from director import Director


def usage():
    print('Usage: Python main plain')
    print('Usage: Python main html')


def main():
    if len(sys.argv) != 2:
        usage()
        sys.exit()

    if sys.argv[1] == 'plain':
        text_builder = TextBuilder()
        director = Director(text_builder)
        director.construct()
        result = text_builder.get_result()
        print(result)
    elif sys.argv[1] == 'html':
        html_builder = HTMLBuilder()
        director = Director(html_builder)
        director.construct()
        filename = html_builder.get_result()
        print(filename + 'A été créé.')
    else:
        usage()
        sys.exit()


if __name__ == "__main__":
    main()

Le fichier principal est un programme de test pour le modèle Builder. Créez un document selon le format spécifié sur la ligne de commande comme indiqué ci-dessous.

python main.py plain ・ ・ ・ Créer un document avec du texte brut python main.py html ・ ・ ・ Création de documents avec fichier HTML

Si vous spécifiez ** plain ** sur la ligne de commande, vous transmettez une instance de la classe TextBuilder au constructeur de classe Director. De plus, si ** html ** est spécifié sur la ligne de commande, une instance de la classe HTMLBuilder est transmise au constructeur de la classe Director.

TextBuilder et HTMLBuilder sont des sous-classes de Builder et Director n'utilise que des méthodes Builder pour créer des documents. Utiliser uniquement les méthodes Builder signifie que ** Director ne sait pas si TextBuilder ou HTMLBuilder est réellement en cours d'exécution **.

Par conséquent, le constructeur doit déclarer un ensemble de méthodes nécessaires et suffisantes pour atteindre l'objectif de construction du document. Cependant, Builder ne doit pas fournir de méthodes spécifiques au texte brut ou aux fichiers HTML.

Résultat d'exécution (clair)

====================
[Greeting]

■ Du matin à midi


● Bonjour.

● Bonjour.


■ La nuit


● Bonsoir.

● Bonne nuit.

● Au revoir.
====================

Résultat d'exécution (html)

`Greeting.html a été créé. '' Greeting.png

Résumé

Un modèle Builder spécialisé pour réduire le travail de création d'instance lorsque la procédure de création d'instance et le contenu sont compliqués.

En ce qui concerne la procédure, la différence entre le modèle de méthode modèle et le modèle Builder est de savoir qui est responsable de l'instanciation. Le modèle de méthode modèle détermine la procédure d'instanciation dans une superclasse. D'autre part, la classe Director (autres classes) est responsable de la procédure de génération du modèle Builder.

La clé du modèle Builder est de savoir qui sait comment créer une instance, c'est-à-dire la classe Director. Il est également important que les utilisateurs des directeurs aient besoin de savoir ce qu'est une instance créée par Builder.

Il semble que le modèle Builder entre en jeu lorsqu'il y a une procédure de création d'une instance, lorsque vous devez créer une instance à l'aide d'une ressource externe ou lorsque vous avez beaucoup d'arguments différents dans le constructeur.

référence

Recommended Posts

Modèle de conception #Builder
Modèle de conception #Adapter
Modèle de conception #Decorator
Modèle de conception #Observer
Modèle de conception #Facade
Modèle de conception #Strategy
Modèle de conception #Singleton
Modèle de conception #Proxy
[Gang of Four] Apprentissage des modèles de conception - Constructeur
Design Pattern #Factory, méthode
Design Pattern #Template, méthode
J'ai écrit un modèle de conception dans l'édition Kotlin Builder
Modèle de conception Oreore: variable glocale
Python Design Pattern - Méthode de modèle
[Gang of Four] Apprentissage des modèles de conception
Résumé du modèle de conception Java GoF
J'ai étudié les modèles de conception (mémo personnel) Partie 3 (modèle de prototype, modèle de constructeur)
Apprenez le modèle de conception "Prototype" avec Python
[Gang of Four] Apprentissage des modèles de conception --Singleton
[Gang of Four] Apprentissage des modèles de conception - Décorateur
[Gang of Four] Apprentissage des modèles de conception - Visiteur
Modèle de conception-Adaptateur
[Gang of Four] Apprentissage des modèles de conception - Médiateur
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
[Gang of Four] Apprentissage des modèles de conception - Itérateur
Modèle de conception du GoF à partir du problème 2. Structure
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
Modèle de conception-Itérateur
[Gang of Four] Apprentissage des modèles de conception - Façade
[Gang of Four] Apprentissage des modèles de conception - Composite
[Gang of Four] Apprentissage des modèles de conception - Prototype
Modèle de conception du GoF à partir du problème 1. Génération
Apprenez le modèle de conception "Iterator" avec Python
[Gang of Four] Apprentissage des modèles de conception --Mémento
[Gang of Four] Apprentissage des modèles de conception - État
[Gang of Four] Apprentissage des modèles de conception - Interprétation
Apprenez le modèle de conception «Stratégie» avec Python
[Gang of Four] Apprentissage des modèles de conception - Pont
Apprenez le modèle de conception "Composite" avec Python
Apprenez le modèle de conception "Singleton" avec Python
Apprenez le modèle de conception "État" en Python
Apprenez le modèle de conception "Adapter" avec Python
[Gang of Four] Apprentissage des modèles de conception - Proxy
[Gang of Four] Apprentissage des modèles de conception - Stratégie
[Gang of Four] Apprentissage des modèles de conception - Adaptateur
Apprenez le modèle de conception "Façade" avec Python
[Gang of Four] Apprentissage des modèles de conception --Observer
[Gang of Four] Apprentissage des modèles de conception - Commande
Modèle de conception GoF à partir du problème 3. Comportement
[Gang of Four] Apprentissage des modèles de conception - Poids du vol
[Gang of Four] Apprentissage des modèles de conception - Usine abstraite
Apprenez le modèle de conception "Abstract Factory" avec Python
Apprenez le modèle de conception "Méthode de modèle" en Python
[Gang of Four] Apprentissage des modèles de conception - Méthode d'usine