【デザインパターン勉強】builderメソッド

ざっくり概要

builderメソッドを自分の言葉でいうと、

作成するメソッドの役割は同じだが、異なる結果を得るプログラムを何個も 作る際、有用なプログラム(パターン) といった感じです。

ここで重要な点は 作成するメソッドの役割は同じ ということです。

本記事で記載したコードは税計算を表示するプログラムです。

登場メソッド

  • set_total(金額インプット)
  • set_tax(税率インプット)
  • message_tax(消費税を計算、出力)

コード

# python3.5.2
import abc

class TaxCalcDirector():
    def __init__(self, builder):
        self.__builder = builder
        
    def construct(self,total,tax):
        self.__builder.set_total(self,total)
        self.__builder.set_tax(self,tax)
        self.__builder.message_tax(self)

class AbstractTaxCalcBuilder(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def set_total(self,total):
        pass

    @abc.abstractmethod
    def set_tax(self,rate):
        pass
        
    @abc.abstractmethod
    def message_tax(self,message):
        pass
    
class ConsumptionTaxBuilder(AbstractTaxCalcBuilder):
    def __init__(self):
        self.rate = 0
        self.total = 0
        
    def set_total(self,total):
        self.total = total
        
    def set_tax(self,rate):
        self.rate = rate
    
    def message_tax(self):
        tax = self.total * self.rate
        message = " ".join(["あなたの払う税金は",str(tax),"円です"])
        print(message)
        
class DeductionTaxBuilder(AbstractTaxCalcBuilder):
    def __init__(self):
        self.rate = 0
        self.total = 0
        
    def set_total(self,total):
        self.total = total
        
    def set_tax(self,rate):
        self.rate = -1 * rate
    
    def message_tax(self):
        tax = self.total * self.rate
        message = " ".join(["あなたが還付される税金は",str(tax),"円です"])
        print(message)

def main():
    # 支払う税金
    tax = TaxCalcDirector(ConsumptionTaxBuilder)
    tax.construct(1000,0.3) #あなたの払う税金は 300.0 円です
    # 還付
    tax = TaxCalcDirector(DeductionTaxBuilder)
    tax.construct(200,0.1) #あなたが還付される税金は -20.0 円です

    
if __name__ == '__main__':
    main()    

main()メソッドでは、行いたい作業(クラス名)をインスタンス化しています。 作業に応じて、 tax = TaxCalcDirector(クラス) #クラス→ ConsumptionTaxBuilderやDeductionTaxBuilder とすることで、クラスの継承を変えて、税の還付金計算に変更することが出来ます。 つまり、具体的な作業を認識せずに処理を変えられます。 今回は消費税計算、税の還付金計算と処理を変えています。

各クラスの役割

AbstractTaxCalcBuilder(Builder)

インスタンスを作成する際に必要な作業(メソッド)を規定しています。 つまり、以下のメソッドとなります。

  • 金額インプット set_total
  • 税率インプット set_tax
  • 消費税を計算、出力 message_tax

メソッドをオーバーライドし忘れを防ぐために抽象クラスとしています。 教科書では Builder と呼ばれますが、「現場監督」といったほうがイメージしやすい気がします。

ConsumptionTaxBuilder(ConcreteBuilder)

AbstractTaxCalcBuilderで定義されたメソッドを具体化しています。

教科書では ConcreteBuilder と呼ばれますが「現場作業員」といったほうがイメージしやすい気がします。

TaxCalcDirector(Director)

AbstractTaxCalcBuilderのメソッドを用いてインスタンスを生成しています。 また、インスタンス作成の際、ConsumptionTaxBuilder継承してインスタンス化しています。

必要な情報は builderのメソッドとConsumptionTaxBuilderというConcreteBuilder のクラス名のみです。

ここで、重要なのは以下の2点です。

  • AbstractTaxCalcBuilder(Builder)のメソッドのみを使っていること
  • 具体的なアウトプットを得る際はConcreteBuilderのクラス名を継承して実行

教科書では Directorと呼ばれて説明されています。監督する立場なのでイメージしやすいですね。

ここでわかることは アウトプットを変更する際、ConcreteBuilderクラス名を修正して実行すればいい

→つまり、クラス名だけで柔軟にアウトプットを変えることが出来るということです。

参考文献

Javaで学ぶデザインパターン入門