전략패턴이란?

  • 동일한 작업을 수행하는 여러 알고리즘(전략)을 인터페이스로 정의하고, 이를 런타임에 교체할 수 있게 해주는 디자인 패턴
  • 알고리즘을 캡슐화하고 유연하게 교체할 수 있는 구조를 제공하여 코드의 유지보수성과 확장성을 크게 향상

전략패턴의 특징

  • 알고리즘 캡슐화: 알고리즘을 인터페이스로 추상화하고, 이를 여러 클래스에서 각각 구현
  • 런타임 교체 가능: 런타임에 전략을 변경할 수 있음
  • 유지보수성 향상: 조건문을 줄이고 새로운 전략을 쉽게 추가 가능
  • 클라이언트 코드와 알고리즘 분리: 클라이언트는 알고리즘 구현에 대해 알 필요 없이 인터페이스만 사용

전략 패턴의 구성 요소

  • Strategy(전략 인터페이스) : 알고리즘을 정의하는 인터페이스
  • ConcreteStrategy(구체적인 전략 클래스) : 전략 인터페이스를 구현하고, 각각의 알고리즘을 캡슐화한 클래스
  • Context(문맥 클래스) :전략을 사용하는 클래스. 전략 객체를 생성자나 세터 메서드로 주입받아 사용

사용 예 : 결제 시스템

1. 전략 인터페이스 정의

public interface PaymentStrategy {
    void pay(int amount);
}

2. 구체적인 전략 클래스 정의

public class CreditCardPayment implements PaymentStrategy {

    @Override
    public void pay(int amount) {
        System.out.println("카드로 결제합니다.");
    }
}

public class BankTransferPayment implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("계좌이체를 통해 결제합니다.");
    }
}

3. 문맥 클래스 정의 : 실제 전략 클래스를 멤버변수로 두어 사용하는 클래스

구성을 통해 전략 클래스를 사용한다. (구성 : A는 B를 가지고 있다.)

public class PaymentContext {
    private PaymentStrategy paymentStrategy;

    // 전략을 생성자를 통해 주입받음
    public PaymentContext(PaymentStrategy paymentStrategy) {
        this.paymentStrategy = paymentStrategy;
    }

    // 전략을 변경할 수 있도록 세터 메서드 제공
    public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
        this.paymentStrategy = paymentStrategy;
    }

    public void pay(int amount) {
        paymentStrategy.pay(amount);
    }
}

4. 클라이언트에서 코드 사용

public class StrategyPatternExample {
    public static void main(String[] args) {
        // 1. Credit Card 결제 전략 사용
        PaymentContext context = new PaymentContext(new CreditCardPayment());
        context.pay(100);

        // 2. Bank Transfer 결제 전략으로 변경 (런타임 환경에서 전략 변경 가능)
        context.setPaymentStrategy(new BankTransferPayment());
        context.pay(300);
    }
}

전략패턴 사용 장단점

전략 패턴의 장점

  1. 알고리즘 교체가 쉬움: 새로운 알고리즘을 추가해도 기존 코드에 영향을 주지 않음
  2. 조건문 제거: if-else 또는 switch문을 대체하여 코드 가독성 향상
  3. 유지보수 용이: 알고리즘이 독립된 클래스로 캡슐화되어, 수정이 쉽고 재사용성이 높음
  4. 유연성: 런타임에 전략을 교체할 수 있어 상황에 맞게 다르게 동작할 수 있음

전략 패턴의 단점

  1. 클래스 수 증가: 각 전략을 독립적인 클래스로 정의해야 하므로, 클래스 수가 많아질 수 있음
  2. 전략 선택 책임: 클라이언트가 적절한 전략을 선택해야 하며, 전략 선택 로직이 복잡해질 수 있음
  3. 단순한 경우에는 오버엔지니어링: 간단한 조건문을 대체하기 위해 사용할 경우 코드가 불필요하게 복잡해질 수 있음

전략 패턴을 적용하면 좋은 실제 사례

  1. 로깅 전략: 다양한 로깅 방식(Console, File, Database 등)을 선택적으로 사용해야 할 때
  2. 데이터 압축: ZIP, RAR, GZIP 등 다양한 압축 방식을 런타임에 교체할 때
  3. 파일 변환: CSV, JSON, XML 등의 포맷 변환을 지원해야 할 때

+ Recent posts