토니의 연습장

Strategy Design Pattern 본문

기타/Miscellaneous

Strategy Design Pattern

bellmake 2025. 3. 27. 17:19
🧩 전략 패턴이란?
전략 패턴이란, 알고리즘이나 로직을 여러 가지로 정의하고, 이것들을 상황에 따라 바꿔가며 사용할 수 있도록 만드는 디자인 패턴이야.

전략 패턴은 크게 3가지 구성 요소로 이루어져 있어.

Strategy (전략): 기능의 인터페이스를 정의하는 역할

Concrete Strategy (구체적 전략): Strategy를 구체적으로 구현한 클래스

Context (컨텍스트): Strategy를 사용하는 클래스. 전략을 상황에 따라 교체할 수 있도록 관리해.

🎯 1단계: 전략 인터페이스 정의 (PaymentMethod)
python
복사
편집
from abc import ABC, abstractmethod

class PaymentMethod(ABC):
    @abstractmethod
    def pay(self, amount):
        pass
추상 클래스(PaymentMethod)는 각 전략이 공통으로 구현해야 하는 메서드를 명시해. 여기서는 pay(amount) 메서드야.

실제로 PaymentMethod 자체로는 인스턴스를 생성할 수 없어. 반드시 하위 클래스에서 pay 메서드를 구현해야 해.

🚩 2단계: 구체적인 전략 구현 (Concrete Strategies)
python
복사
편집
class CreditCardPayment(PaymentMethod):
    def pay(self, amount):
        return f"Paying {amount} using Credit Card."

class PayPalPayment(PaymentMethod):
    def pay(self, amount):
        return f"Paying {amount} using PayPal."

class BitcoinPayment(PaymentMethod):
    def pay(self, amount):
        return f"Paying {amount} using Bitcoin."
인터페이스(PaymentMethod)를 상속하여 다양한 전략(결제 방식)을 구체적으로 구현한 클래스들이야.

각각의 클래스는 동일한 pay 메서드를 갖지만, 결제 방법이 다르게 구현된 것을 볼 수 있어.

새로운 결제 방식이 추가될 때 이 부분만 수정하면 돼.

🛒 3단계: Context 클래스 구현 (ShoppingCart)
python
복사
편집
class ShoppingCart:
    def __init__(self, payment_method: PaymentMethod):
        self.payment_method = payment_method

    def checkout(self, amount):
        return self.payment_method.pay(amount)
ShoppingCart 클래스는 전략을 사용하는 클래스(Context)로, 결제 방식을 외부에서 전달받아서 상황에 맞는 전략을 사용하도록 해.

생성자에서 결제 방식을 받아서 객체에 저장하고, 나중에 checkout 메서드를 호출하면 그 전략을 사용해 결제를 처리하지.

여기서 전략을 바꾸려면 다른 전략을 전달하기만 하면 돼.

⚙️ 4단계: Context에서 전략 사용하기 (Main 실행 부분)
python
복사
편집
if __name__ == "__main__":
    cart = ShoppingCart(CreditCardPayment())
    print(cart.checkout(100))  # Paying 100 using Credit Card.

    cart = ShoppingCart(PayPalPayment())
    print(cart.checkout(200))  # Paying 200 using PayPal.

    cart = ShoppingCart(BitcoinPayment())
    print(cart.checkout(300))  # Paying 300 using Bitcoin.
이 부분이 실제 전략 패턴을 활용하는 부분으로,
ShoppingCart에 각각 다른 전략(CreditCardPayment, PayPalPayment, BitcoinPayment)을 전달하여 다양한 결제 방식을 사용할 수 있음을 보여주고 있어.

같은 ShoppingCart라는 클래스의 인터페이스를 유지하면서도 결제 전략만을 변경하여 다양한 동작을 수행하도록 만든 것이 핵심이야.

📌 전략 패턴의 장점:
코드의 유지 보수가 쉬워져.

새로운 전략이 추가되더라도 기존 코드는 변경할 필요가 없어.

실행 시간에도 손쉽게 전략을 변경할 수 있어.

예를 들어 나중에 "카카오페이 결제"를 추가하고 싶다면, 아래와 같이 클래스를 하나 더 만들어서 전략만 추가하면 간단하게 확장할 수 있어:

python
복사
편집
class KakaoPayPayment(PaymentMethod):
    def pay(self, amount):
        return f"Paying {amount} using KakaoPay."

# 사용 예시
cart = ShoppingCart(KakaoPayPayment())
print(cart.checkout(400))  # Paying 400 using KakaoPay.
이런 방식으로 전략 패턴은 유연한 시스템 확장과 유지보수를 도와줘.

 

활용 예시 - Data Statistics Inspection

from abc import ABC, abstractmethod

import pandas as pd


# Abstract Base Class for Data Inspection Strategies
# --------------------------------------------------
# This class defines a common interface for data inspection strategies.
# Subclasses must implement the inspect method.
class DataInspectionStrategy(ABC):
    @abstractmethod
    def inspect(self, df: pd.DataFrame):
        """
        Perform a specific type of data inspection.

        Parameters:
        df (pd.DataFrame): The dataframe on which the inspection is to be performed.

        Returns:
        None: This method prints the inspection results directly.
        """
        pass


# Concrete Strategy for Data Types Inspection
# --------------------------------------------
# This strategy inspects the data types of each column and counts non-null values.
class DataTypesInspectionStrategy(DataInspectionStrategy):
    def inspect(self, df: pd.DataFrame):
        """
        Inspects and prints the data types and non-null counts of the dataframe columns.

        Parameters:
        df (pd.DataFrame): The dataframe to be inspected.

        Returns:
        None: Prints the data types and non-null counts to the console.
        """
        print("\nData Types and Non-null Counts:")
        print(df.info())


# Concrete Strategy for Summary Statistics Inspection
# -----------------------------------------------------
# This strategy provides summary statistics for both numerical and categorical features.
class SummaryStatisticsInspectionStrategy(DataInspectionStrategy):
    def inspect(self, df: pd.DataFrame):
        """
        Prints summary statistics for numerical and categorical features.

        Parameters:
        df (pd.DataFrame): The dataframe to be inspected.

        Returns:
        None: Prints summary statistics to the console.
        """
        print("\nSummary Statistics (Numerical Features):")
        print(df.describe())
        print("\nSummary Statistics (Categorical Features):")
        print(df.describe(include=["O"]))


# Context Class that uses a DataInspectionStrategy
# ------------------------------------------------
# This class allows you to switch between different data inspection strategies.
class DataInspector:
    def __init__(self, strategy: DataInspectionStrategy):
        """
        Initializes the DataInspector with a specific inspection strategy.

        Parameters:
        strategy (DataInspectionStrategy): The strategy to be used for data inspection.

        Returns:
        None
        """
        self._strategy = strategy

    def set_strategy(self, strategy: DataInspectionStrategy):
        """
        Sets a new strategy for the DataInspector.

        Parameters:
        strategy (DataInspectionStrategy): The new strategy to be used for data inspection.

        Returns:
        None
        """
        self._strategy = strategy

    def execute_inspection(self, df: pd.DataFrame):
        """
        Executes the inspection using the current strategy.

        Parameters:
        df (pd.DataFrame): The dataframe to be inspected.

        Returns:
        None: Executes the strategy's inspection method.
        """
        self._strategy.inspect(df)


# Example usage
if __name__ == "__main__":
    # Example usage of the DataInspector with different strategies.

    # Load the data
    # df = pd.read_csv('../extracted-data/your_data_file.csv')

    # Initialize the Data Inspector with a specific strategy
    # inspector = DataInspector(DataTypesInspectionStrategy())
    # inspector.execute_inspection(df)

    # Change strategy to Summary Statistics and execute
    # inspector.set_strategy(SummaryStatisticsInspectionStrategy())
    # inspector.execute_inspection(df)
    pass

'기타 > Miscellaneous' 카테고리의 다른 글

오픈소스 AI 툴/스택/프레임워크  (0) 2025.03.27
Factory Design Pattern  (2) 2025.03.27
CUDA와 cuda-toolkit 버전 차이?  (1) 2024.11.21