こんにちは、ユウです。
現在、デザインパターンについて勉強しています。本記事ではStrategyパターンについて紹介したいと思います。
以下の2つの書籍で勉強していますが、わかりやすくておすすめです!
Strategyパターン
Strategyというのは「戦略」という意味で、プログラミングの文脈では「アルゴリズム」を意味すると考えられます。
Strategyパターンは、戦略(アルゴリズム)の切り替えを容易にするためのパターンです。
Strategyパターンを使うことでプログラムの実行時にアルゴリズムを切り替えることもできます。
Strategyパターンには以下の3つの登場人物がいます:
Strategy(戦略)
戦略を利用するためのインターフェースを定める役です。
Concrete Strategy(具体的戦略)
Strategy役のインターフェースを実際に実装する役です。
Context(文脈)
Strategy役を利用する役です。
Context役は、Concrete Strategy役のインスタンスを状態として保持し、それを必要に応じて使用します。言い換えると、Context役は、処理の一部(アルゴリズム)をConcrete Strategy役に委譲します。
以下、Strategyパターンのクラス図です。
サンプルコード
以下、Strategyパターンを使ったサンプルコードとして、お金の支払い方法(アルゴリズム)を切り替える例を考えます。
支払い方法としては、1. 現金を使った支払い、2. クレジットカードを使った支払い、を考え、これらを切り替えられるようにします。
Strategy
まず、インターフェースであるStrategy役として、以下のPaymentStrategy
を実装します。
PaymentStrategy
は、お金を支払うメソッド(pay
)を抽象メソッドとして備えます。
# payment_strategy.py
from abc import ABC, abstractmethod
class PaymentStrategy(ABC):
@abstractmethod
def pay(self, amount):
pass
Concrete Strategy
上で定義したインターフェースの実装として、2つのConcrete Strategy役のクラスを実装します。
(1) 現金での支払いに対応するConcrete Strategy
# cash_payment.py
from payment_strategy import PaymentStrategy
class CashPayment(PaymentStrategy):
def pay(self, amount):
print(f"現金で{amount}円支払います")
(2) クレジットカードでの支払いに対応するConcrete Strategy
# credit_card_payment.py
from payment_strategy import PaymentStrategy
class CreditCardPayment(PaymentStrategy):
def __init__(self, card_number):
self.card_number = card_number
def pay(self, amount):
print(f"クレジットカード{self.card_number}で{amount}円支払います")
Context
Concrete Strategyを利用するContext役のクラスとして、以下のPerson
クラスを実装します。
Personクラスは、初期化時にConcrete Strategyを受け取ります。
また、Person
クラスはお金を支払うためのメソッド(pay
)を持ちますが、その処理はConcrete Strategyのpayメソッドを呼ぶだけです。つまり、Person
クラスのpay
メソッドは、処理をConcrete Strategyに委譲しています。
また、Person
クラスは、支払い方法を切り替えるためのメソッド(set_payment_strategy
)を持ちます。
# person.py
from payment_strategy import PaymentStrategy
class Person:
# 初期化時にConcrete Strategyのインスタンスを受け取る
def __init__(self, payment_strategy: PaymentStrategy):
self.payment_strategy = payment_strategy
# インターフェースを用いてメソッドを実装する
def pay(self, amount):
self.payment_strategy.pay(amount)
# Concrete Strategyを切り替えるメソッド
def set_payment_strategy(self, payment_strategy: PaymentStrategy):
self.payment_strategy = payment_strategy
以上で定義した各クラスを用いて、支払い方法(アルゴリズム)を切り替えるコードは以下となります。
# main.py
from cash_payment import CashPayment
from credit_card_payment import CreditCardPayment
from person import Person
def main():
# 現金で支払う場合
person = Person(CashPayment())
person.pay(100)
# クレジットカードで支払う場合
credit_card_payment = CreditCardPayment("1234-5678-9012-3456")
person = Person(credit_card_payment)
person.pay(200)
# クレジットカード→現金に支払い方法を変更する
person.set_payment_strategy(CashPayment())
person.pay(300)
if __name__ == "__main__":
main()
上記の実行結果は以下となります。
現金で100円支払います
クレジットカード1234-5678-9012-3456で200円支払います
現金で300円支払います
たしかに、支払い方法(アルゴリズム)を切り替えられていますね。
まとめ
本記事ではStrategyパターンを紹介しました。
引き続きデザインパターンの勉強を進めたいと思います。
コメント