戦略設計パターン

Barbara Streisand
Barbara Streisandオリジナル
2024-11-27 15:05:12726ブラウズ

Strategy Design Pattern

戦略設計パターンは、実行時のアルゴリズムの動作の選択を可能にする動作設計パターンです。

単一のクラスでアルゴリズムの複数のバリエーションを実装するの代わりに、アルゴリズムのファミリーを定義し、それぞれを独自のクラスにカプセル化し、それらを交換可能にすることができます。

戦略パターン (UML) のコンポーネント:

  1. Context クラス: Strategy オブジェクトへの参照を維持し、共通のインターフェイスを通じてオブジェクトと対話します。

    • 例: User クラスは、品質と AdPolicy のさまざまな戦略と対話します。
  2. 戦略インターフェイス: すべての具体的な戦略に共通のインターフェイスを定義します。

    • 例: 品質と ADPolicies は、動作を定義する抽象インターフェイスです。
  3. 具体的な戦略: 特定のアルゴリズムを使用して戦略インターフェイスを実装します。

    • 例: FreeUserQuality、PremiumUserQuality、BasicUserQuality、FreeUserAdPolicy など

戦略パターンを使用する場合

柔軟性と保守性の利点が複数の戦略クラスを管理するオーバーヘッドを上回る場合は、戦略パターンを使用します。

  1. 多くのアルゴリズム:

    • 単一クラス内でアルゴリズムまたは動作の複数のバリエーションを定義する必要がある場合。
    • 例: さまざまなサブスクリプション プラン (無料、ベーシック、プレミアム) のビデオ品質を定義します。
  2. 実行時の決定:

    • ユーザー入力またはその他の実行時条件に基づいてクラスの動作を動的に変更する必要がある場合。
    • 例: 実行時に圧縮アルゴリズム (ZIP、RAR、7z) を選択します。
  3. if または switch ステートメントの過度の使用を避ける:

    • 条件ロジックを交換可能な戦略クラスに置き換えます。
    • 例: 大規模な if-else ブロックを使用しない支払い処理 (クレジット カード、PayPal、UPI)。
  4. バリエーションのカプセル化:

    • コンテキスト クラスをクリーンに保つために、アルゴリズムのバリエーションを別のクラスにカプセル化します。
    • 例: ロギング戦略 (ConsoleLogger、FileLogger、RemoteLogger)。
  5. オープン/クローズの原則:

    • 既存のコードを変更せずに新しい戦略を追加することで、システムが拡張にはオープンであるが、変更にはクローズされていることを確認します。
    • 例: サンプル システムに新しいユーザー タイプ (EnterpriseUserQuality) を追加します。

例:

from abc import ABC, abstractmethod
from enum import Enum

# Enum for User Types
class UserType(Enum):
    FREE = 0
    BASIC = 1
    PREMIUM = 2

# Strategy Interface for Quality
class Quality(ABC):
    @abstractmethod
    def get_quality(self):
        pass

# Strategy Interface for Ad Policy
class AdPolicy(ABC):
    @abstractmethod
    def has_ads(self):
        pass

# Concrete Strategy for Quality
class FreeUserQuality(Quality):
    def get_quality(self):
        return ['SD']

class BasicUserQuality(Quality):
    def get_quality(self):
        return ['SD', 'HD']

class PremiumUserQuality(Quality):
    def get_quality(self):
        return ['SD', 'HD', 'UHD']

# Concrete Strategy for Ad Policy
class FreeUserAdPolicy(AdPolicy):
    def has_ads(self):
        return True

class BasicUserAdPolicy(AdPolicy):
    def has_ads(self):
        return True

class PremiumUserAdPolicy(AdPolicy):
    def has_ads(self):
        return False

# Context Class
class User:
    def __init__(self, user_type: UserType, quality: Quality, ad_policy: AdPolicy):
        self.user_type = user_type
        self.quality = quality
        self.ad_policy = ad_policy

    def get_quality(self):
        return self.quality.get_quality()

    def has_ads(self):
        return self.ad_policy.has_ads()

# Usage
free_user = User(UserType.FREE, FreeUserQuality(), FreeUserAdPolicy())
basic_user = User(UserType.BASIC, BasicUserQuality(), BasicUserAdPolicy())
premium_user = User(UserType.PREMIUM, PremiumUserQuality(), PremiumUserAdPolicy())

print("Free User Quality:", free_user.get_quality())  # ['SD']
print("Free User Ads:", free_user.has_ads())          # True

print("Premium User Quality:", premium_user.get_quality())  # ['SD', 'HD', 'UHD']
print("Premium User Ads:", premium_user.has_ads())          # False

戦略パターンの利点:

  1. 柔軟性: コンテキスト クラスを変更せずに、実行時にアルゴリズムを交換できます。
  2. 拡張性: 既存のコードを変更せずに新しい戦略を追加できます。
  3. 可読性とメンテナンス: ロジックを特定の戦略クラスに委任することで、メイン クラスの煩雑さを軽減します。
  4. SOLID 原則の遵守: 特にオープン/クローズ原則をサポートします。

戦略パターンの欠点:

  1. 複雑さの増加: 管理するクラスとオブジェクトが追加されました。
  2. オーバーヘッド: 戦略の数が少ない場合、または変更頻度が低い場合、パターンにより不必要な複雑さが追加される可能性があります。

追加の例

  1. 並べ替えアルゴリズム: さまざまな並べ替え戦略 (QuickSort、MergeSort、BubbleSort など) を動的に使用します。
  2. 割引計算: ユーザーのタイプに基づいて、さまざまな割引戦略 (FlatDiscount、PercentageDiscount) を適用します。
  3. 認証メカニズム: 異なる認証方法 (OAuth、JWT、BasicAuth) 間の切り替え。

以上が戦略設計パターンの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。