knowledge/technology/dev/programming/patterns/behavioral/Strategy Pattern.md
2024-01-17 09:00:45 +01:00

73 lines
No EOL
3.5 KiB
Markdown

---
obj: concept
---
# Strategy Pattern
## **Description:**
The Strategy Pattern is a behavioral design pattern that defines a family of algorithms, encapsulates each one of them, and makes them interchangeable. It allows clients to choose an appropriate algorithm from a family of algorithms at runtime, without altering the code that uses the algorithm. This pattern promotes flexibility, extensibility, and the ability to switch between different algorithms or strategies.
**How it's Used:**
1. **Strategy Interface/Abstract Class**: Define a strategy interface or abstract class that declares a method or a set of methods for the algorithms to be encapsulated.
2. **Concrete Strategies**: Create concrete strategy classes that implement the strategy interface/abstract class. Each concrete strategy represents a specific algorithm.
3. **Context**: Define a context class that contains a reference to a strategy object and can switch between different strategies. The context class uses the strategy object to perform its operations.
4. **Client Code**: Clients create instances of the context class and configure them with the desired strategy. Clients can change the strategy at runtime, and the context will use the currently configured strategy to perform its tasks.
## **Example:**
Let's create an example of the Strategy Pattern in [Python](../../languages/Python.md) to model a payment system where customers can choose different payment methods.
```python
from abc import ABC, abstractmethod
# Step 1: Strategy Interface
class PaymentStrategy(ABC):
@abstractmethod
def pay(self, amount):
pass
# Step 2: Concrete Strategies
class CreditCardPayment(PaymentStrategy):
def pay(self, amount):
print(f"Paying ${amount} using Credit Card.")
class PayPalPayment(PaymentStrategy):
def pay(self, amount):
print(f"Paying ${amount} using PayPal.")
class BankTransferPayment(PaymentStrategy):
def pay(self, amount):
print(f"Paying ${amount} using Bank Transfer.")
# Step 3: Context (PaymentContext)
class PaymentContext:
def __init__(self, strategy):
self.strategy = strategy
def set_payment_strategy(self, strategy):
self.strategy = strategy
def perform_payment(self, amount):
self.strategy.pay(amount)
# Step 4: Client Code
def main():
credit_card_strategy = CreditCardPayment()
paypal_strategy = PayPalPayment()
bank_transfer_strategy = BankTransferPayment()
context = PaymentContext(credit_card_strategy)
context.perform_payment(100.0)
# Change payment strategy at runtime
context.set_payment_strategy(paypal_strategy)
context.perform_payment(50.0)
context.set_payment_strategy(bank_transfer_strategy)
context.perform_payment(75.0)
if __name__ == "__main__":
main()
```
In this [Python](../../languages/Python.md) example, we define a `PaymentStrategy` interface (Step 1) with a `pay` method. We create three concrete strategy classes (`CreditCardPayment`, `PayPalPayment`, and `BankTransferPayment`) (Step 2) that implement this interface, representing different payment methods.
The `PaymentContext` class (Step 3) is the context class that contains a reference to a strategy object and uses it to perform payments. Clients (Step 4) create instances of the context class and configure them with the desired payment strategy. Clients can change the strategy at runtime, and the context will use the currently configured strategy to perform payments. This allows for easy swapping of payment methods without changing the client code.