본문 바로가기

Architecture/Design Pattern

[Design Pattern] 전략 (Strategy) 패턴이란?

전략 패턴?

실행 중에 알고리즘 전략을 선택하여 객체 동작을 실시간으로 바뀌도록 할 수 있게 하는 행동 패턴

 

 

 

핵심 아이디어

 

  • 동일한 문제를 해결하는 여러 알고리즘이 있을 때, 각 알고리즘을 별도의 클래스로 캡슐화
  • 런타임에 알고리즘을 선택하여 교체 가능
  • 조건문(if-else, switch) 대신 객체 위임을 통한 알고리즘 선택

 

 

구조

 

 

 

 

실무 예제: Java Comparator

public class ComparatorExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("John", "Alice", "Bob", "Charlie");
        
        // 전략 1: 알파벳 순 정렬
        Collections.sort(names, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.compareTo(s2);
            }
        });
        System.out.println("알파벳 순: " + names);
        
        // 전략 2: 길이 순 정렬
        Collections.sort(names, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.length() - s2.length();
            }
        });
        System.out.println("길이 순: " + names);
        
        // 전략 3: 역순 정렬 (람다 사용)
        names.sort((s1, s2) -> s2.compareTo(s1));
        System.out.println("역순: " + names);
    }
}

전략 패턴 적용 원리

  • Strategy 인터페이스: Comparator<T>
  • ConcreteStrategy: 각각의 익명 클래스 또는 람다 표현식
  • Context: Collections.sort() 또는 List.sort() 메서드

정렬이라는 동일한 작업을 수행하지만, 비교 기준(알고리즘)을 런타임에 교체할 수 있다.

 

 

 

직접 구현: 쇼핑몰 결제 시스템

쇼핑몰에서 다양한 결제 수단을 지원하는 시스템을 전략 패턴으로 구현해보았다.

 

1. Strategy 인터페이스

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

 

 

2. ConcreteStrategy 구현

// 마스터 카드 결제 전략
public class MasterCardStrategy implements PaymentStrategy {
    private String name;
    private String cardNumber;
    private String cvv;

    public MasterCardStrategy(String name, String cardNumber, String cvv) {
        this.name = name;
        this.cardNumber = cardNumber;
        this.cvv = cvv;
    }

    @Override
    public void pay(int amount) {
        System.out.println(amount + " Won paid using Master Card");
    }
}

// 모바일 결제 전략
public class MobilePayStrategy implements PaymentStrategy {
    private String email;
    private String password;

    public MobilePayStrategy(String email, String password) {
        this.email = email;
        this.password = password;
    }

    @Override
    public void pay(int amount) {
        System.out.println(amount + " Won paid using Mobile Pay");
    }
}

 

3. Context 클래스

public class Item {
    private String name;
    private int price;

    public Item(String name, int price) {
        this.name = name;
        this.price = price;
    }

    public int getPrice() {
        return price;
    }
}

public class ShoppingCart {
    private List<Item> items;
    private PaymentStrategy paymentStrategy;

    public ShoppingCart() {
        this.items = new ArrayList<>();
    }

    public void addItem(Item item) {
        this.items.add(item);
    }

    public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
        this.paymentStrategy = paymentStrategy;
    }

    public void pay() {
        int amount = 0;
        for (Item item : items) {
            amount += item.getPrice();
        }
        this.paymentStrategy.pay(amount);
    }
}

 

4. Client 코드

public class Client {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();
        cart.addItem(new Item("Macbook Pro", 10000));
        cart.addItem(new Item("IPhone", 2000));

        // 전략 1: 마스터 카드로 결제
        cart.setPaymentStrategy(new MasterCardStrategy("Dmori", "1234-1234-1234-1234", "123"));
        cart.pay();

        // 전략 2: 모바일 페이로 결제
        cart.setPaymentStrategy(new MobilePayStrategy("example@naver.com", "12345"));
        cart.pay();
    }
}

 

5. 실행 결과

12000 Won paid using Master Card
12000 Won paid using Mobile Pay

 

 

 

장단점

전략 패턴의 장점

  1. 개방-폐쇄 원칙(OCP): 새로운 결제 수단을 추가할 때 기존 코드를 수정하지 않고 새로운 전략 클래스만 추가하면 된다.
  2. 단일 책임 원칙(SRP): 각 결제 방식의 로직이 독립적인 클래스로 분리되어 있다.
  3. 런타임 유연성: 실행 중에 전략을 동적으로 교체할 수 있다.
  4. 테스트 용이성: 각 전략을 독립적으로 테스트할 수 있다.
  5. 조건문 제거: 복잡한 if-else나 switch 문을 객체로 대체할 수 있다.

전략 패턴의 단점

  1. 클래스 증가: 전략마다 별도의 클래스가 필요하므로 클래스 개수가 증가한다.
  2. 클라이언트의 인지: 클라이언트가 각 전략의 차이를 알아야 적절한 전략을 선택할 수 있다.
  3. 과도한 설계: 알고리즘이 하나뿐이거나 변경 가능성이 낮으면 오버엔지니어링이 될 수 있다.

 

 

전략 패턴 vs 상태 패턴

많은 사람들이 전략 패턴과 상태 패턴을 혼동하는데, 중요한 차이가 있다:

구분 전략 패턴 상태 패턴
목적 알고리즘 교체 상태에 따른 행동 변경
전환 클라이언트가 명시적으로 전략 선택 상태가 자동으로 전이됨
관계 전략들은 독립적 상태들은 서로 연관됨
예시 결제 수단 선택 노트북 전원 상태

 

 

 

마무리

전략 패턴은 알고리즘의 변경이 빈번하거나 여러 알고리즘 중 하나를 선택해야 하는 상황에서 매우 유용한 디자인 패턴이다.

Java의 Comparator처럼 실무에서도 널리 사용되고 있으며, 코드의 유연성과 확장성을 크게 향상시킬 수 있다.

 

구현 코드:

https://github.com/Dimo-2562/DesignPatternStudy/pull/4

'Architecture > Design Pattern' 카테고리의 다른 글

[Design Pattern] 싱글톤 (Singleton) 패턴이란?  (0) 2025.12.01