Python上級

上級 Pythonで学ぶデザインパターン|練習問題編

導入

デザインパターンは、ソフトウェア設計における問題解決のための再利用可能な方法論です。特に、Pythonのような高水準言語では、設計パターンを適用することで、コードの可読性や保守性を高めることができます。本記事では、実務でよく遭遇する「ストラテジーパターン」を取り上げ、具体的なシチュエーションに基づいて解説します。

教科書レベルの解説(デザインパターン)

重要な概念の整理

ストラテジーパターンは、アルゴリズムをカプセル化し、互いに置き換え可能にすることで、クライアントコードが特定のアルゴリズムに依存しないようにします。これにより、実行時にアルゴリズムを選択したり、追加したりすることが容易になります。例えば、異なる税計算方法を選択するシステムにおいて、ストラテジーパターンを使用することで、税計算のロジックを簡単に変更できます。

コード例(Python)


class TaxStrategy:
    def calculate_tax(self, income):
        raise NotImplementedError("Subclasses should implement this!")

class StandardTax(TaxStrategy):
    def calculate_tax(self, income):
        return income * 0.2

class ReducedTax(TaxStrategy):
    def calculate_tax(self, income):
        return income * 0.1

class TaxCalculator:
    def __init__(self, strategy: TaxStrategy):
        self.strategy = strategy

    def set_strategy(self, strategy: TaxStrategy):
        self.strategy = strategy

    def calculate(self, income):
        return self.strategy.calculate_tax(income)

# 使用例
calculator = TaxCalculator(StandardTax())
print(calculator.calculate(10000))  # 2000.0
calculator.set_strategy(ReducedTax())
print(calculator.calculate(10000))  # 1000.0

コードの行ごとの解説

  1. class TaxStrategy: – 基底クラスとして、税計算のためのインターフェースを定義。
  2. def calculate_tax(self, income): – サブクラスで実装されるべきメソッド。
  3. class StandardTax(TaxStrategy): – 標準税率を計算する具体的な戦略クラス。
  4. def calculate_tax(self, income): – 標準税率を適用した計算を実装。
  5. class ReducedTax(TaxStrategy): – 割引税率を計算する具体的な戦略クラス。
  6. class TaxCalculator: – 税計算を行うためのコンテナクラス。
  7. def set_strategy(self, strategy: TaxStrategy): – 税計算戦略を設定するメソッド。
  8. def calculate(self, income): – 現在の戦略を用いて税を計算するメソッド。
  9. calculator = TaxCalculator(StandardTax()) – 初期戦略として標準税を設定したインスタンスを生成。
  10. calculator.set_strategy(ReducedTax()) – 戦略を変更して再計算。

練習問題編

以下の練習問題に取り組み、理解を深めましょう。

  1. 問題1: 新しい税計算戦略「LuxuryTax」を実装してください。税率は30%です。

    
    class LuxuryTax(TaxStrategy):
        def calculate_tax(self, income):
            return income * 0.3
    
  2. 問題2: 税計算を行う際に、税率を動的に変更できるようにしてください。例えば、税率を引数として受け取るようにします。

    
    class DynamicTax(TaxStrategy):
        def __init__(self, rate):
            self.rate = rate
    
        def calculate_tax(self, income):
            return income * self.rate
    
  3. 問題3: 税計算結果をログに記録する機能を追加してください。

    
    import logging
    
    logging.basicConfig(level=logging.INFO)
    
    class TaxCalculator:
        # ... (既存のコード)
    
        def calculate(self, income):
            result = self.strategy.calculate_tax(income)
            logging.info(f"Calculated tax: {result}")
            return result
    
  4. 問題4: 複数の戦略を同時に使用し、合計税額を計算する機能を追加してください。

    
    class CompositeTaxCalculator:
        def __init__(self, strategies):
            self.strategies = strategies
    
        def calculate(self, income):
            total_tax = sum(strategy.calculate_tax(income) for strategy in self.strategies)
            return total_tax
    

まとめ

  • ストラテジーパターンを利用することで、アルゴリズムの変更が容易になります。
  • 具体的なシチュエーションに応じて適切な戦略を選択することが、実務において重要です。
  • 練習問題を通じて、デザインパターンの理解を深めることができます。