🦧

Strategy

2023/09/10に公開

Strategy デザインパターンは、アルゴリズムのセットを定義し、それぞれのアルゴリズムをカプセル化するもので、これによりアルゴリズムを互いに独立して変更したり交換したりできます。

基本的には、アルゴリズムの実装の詳細を隠蔽しながら、クライアント側から異なるアルゴリズムや戦略を選択・交換する能力を提供します。

Strategy パターンの具体的な例:ソートアルゴリズム

例として、異なる種類のソートアルゴリズムを適用するシステムを考えます。

  1. Strategy (インターフェース/抽象クラス)

    from abc import ABC, abstractmethod
    
    class SortStrategy(ABC):
        @abstractmethod
        def sort(self, dataset: list) -> list:
            pass
    
    
  2. Concrete Strategies (実際のアルゴリズムの実装)

    class BubbleSort(SortStrategy):
        def sort(self, dataset: list) -> list:
            # Bubble sort algorithm
            n = len(dataset)
            for i in range(n):
                for j in range(0, n-i-1):
                    if dataset[j] > dataset[j+1]:
                        dataset[j], dataset[j+1] = dataset[j+1], dataset[j]
            return dataset
    
    class QuickSort(SortStrategy):
        def sort(self, dataset: list) -> list:
            # Quick sort algorithm
            if len(dataset) <= 1:
                return dataset
            pivot = dataset[len(dataset) // 2]
            left = [x for x in dataset if x < pivot]
            middle = [x for x in dataset if x == pivot]
            right = [x for x in dataset if x > pivot]
            return self.sort(left) + middle + self.sort(right)
    
    
  3. Context (Strategyを利用するクラス)

    class SortContext:
        def __init__(self, strategy: SortStrategy):
            self._strategy = strategy
    
        def execute_sort(self, dataset: list) -> list:
            return self._strategy.sort(dataset)
    
    
  4. クライアントコード

    data = [3, 2, 4, 1, 5]
    
    # Bubble sort strategy
    bubble_strategy = BubbleSort()
    context = SortContext(bubble_strategy)
    print(context.execute_sort(data.copy()))
    
    # Quick sort strategy
    quick_strategy = QuickSort()
    context = SortContext(quick_strategy)
    print(context.execute_sort(data.copy()))
    
    

このように、Strategy パターンを使用すると、異なるソートアルゴリズムを容易に交換することができ、コードの柔軟性と再利用性を向上させることができます。

利点:

  1. 柔軟性: Strategy パターンは、簡単に新しい戦略やアルゴリズムを追加することができます。一方、すべてのソートメソッドを1つのクラスに統合すると、そのクラスは徐々に大きくなり、管理や拡張が難しくなる可能性があります。
  2. 再利用性: 個々の戦略は独立しているため、他のコンテキストやアプリケーションで再利用することが容易です。
  3. Open/Closed Principle (開閉の原則): 既存のコードを変更せずに(閉じて)、新しい戦略やアルゴリズムを簡単に追加(開いて)できます。
  4. 単一の責任の原則: 各戦略クラスは、特定のタスクやアルゴリズムの実装に集中します。これにより、各クラスの責任が明確になり、コードが読みやすくなります。
  5. 動的な切り替え: 実行時に動的に戦略を切り替えることが可能です。これにより、クライアントは実行時に最適な戦略を選択し、適用することができます。
  6. テストの容易さ: 各戦略は独立しているため、単体テストを実施するのが簡単です。各アルゴリズムや戦略を個別にテストすることで、コードの品質を高めることができます。

一方、すべてのソートメソッドを1つのクラスに統合するアプローチも確かにシンプルで理解しやすい場合があります。ただし、上述の利点を最大限に活用するためには、Strategy パターンの使用を検討する価値があります。適切なアプローチは、プロジェクトの要件や目的、将来の拡張性などの要因によって異なります。

Discussion