<一覧に戻る

ストラテジーパターン

ストラテジーパターンは、アルゴリズムをクラスとして定義し、それぞれのアルゴリズムを独立させることで、クライアントが必要に応じてアルゴリズムを選択できるようにするデザインパターンです。このパターンを使用すると、アルゴリズムの変更が容易になり、コードの再利用性が高まります。

ストラテジーパターンの構成要素

ストラテジーパターンは以下の3つの要素で構成されています。

  1. ストラテジー(Strategy): アルゴリズムのインターフェースを定義します。
  2. コンテキスト(Context): ストラテジーを利用するクラスで、ストラテジーを変更するためのメソッドを持っています。
  3. 具体的なストラテジー(Concrete Strategy): ストラテジーインターフェースを実装する具体的なアルゴリズムを提供します。

サンプルコード

以下の例では、異なる割引戦略を持つオンラインストアのシナリオを考えます。割引戦略として「通常割引」と「セール割引」を実装します。

ストラテジーインターフェースの定義

from abc import ABC, abstractmethod

class DiscountStrategy(ABC):
    @abstractmethod
    def apply_discount(self, price: float) -> float:
        pass

このコードでは、DiscountStrategyという抽象クラスを定義し、apply_discountメソッドを抽象メソッドとして宣言しています。このメソッドは、価格に対する割引を適用するために実装される必要があります。

具体的なストラテジーの実装

次に、具体的な割引戦略を2つ実装します。

class NoDiscount(DiscountStrategy):
    def apply_discount(self, price: float) -> float:
        return price

class SaleDiscount(DiscountStrategy):
    def apply_discount(self, price: float) -> float:
        return price * 0.8  # 20%の割引
  • NoDiscountクラスは、割引を適用しない戦略を実装します。
  • SaleDiscountクラスは、20%の割引を適用する戦略を実装します。

コンテキストの定義

次に、ストラテジーを使用するクラスを定義します。

class ShoppingCart:
    def __init__(self):
        self.items = []
        self.discount_strategy = NoDiscount()  # デフォルトの割引戦略

    def add_item(self, price: float):
        self.items.append(price)

    def set_discount_strategy(self, strategy: DiscountStrategy):
        self.discount_strategy = strategy

    def calculate_total(self) -> float:
        total = sum(self.items)
        return self.discount_strategy.apply_discount(total)

ShoppingCartクラスは、アイテムを追加し、合計金額を計算するためのメソッドを持っています。また、割引戦略を設定するためのメソッドも提供しています。

サンプルの使用法

最後に、これらのクラスを使用してストラテジーパターンを実際に動かしてみましょう。

if __name__ == "__main__":
    cart = ShoppingCart()
    cart.add_item(100)
    cart.add_item(200)

    print("合計金額(割引なし):", cart.calculate_total())

    cart.set_discount_strategy(SaleDiscount())
    print("合計金額(20%割引):", cart.calculate_total())

このコードを実行すると、割引なしの合計金額と20%割引を適用した合計金額が表示されます。

まとめ

ストラテジーパターンは、アルゴリズムをクラスとして定義し、必要に応じて変更できる柔軟性を提供します。このパターンを使用することで、コードの再利用性が高まり、保守性も向上します。異なるアルゴリズムを簡単に追加・変更できるため、システムの拡張が容易になります。

一覧に戻る

出力結果: