GoF에서 가장 많이 혼동되는 한 쌍. 클래스 다이어그램이 사실상 같기 때문이다.
둘 다 인터페이스 + 여러 구현 + 컨텍스트가 위임
세 가지로 가른다
Strategy State
누가 바꾸나 클라이언트가 밖에서 주입 객체가 스스로 전이
서로를 아나 모른다 (독립·대체 가능) 안다 (전이 관계를 갖는다)
무엇을 답하나 "어떻게 할까" "지금 무엇인가"
// Strategy — 밖에서 고른다. 정렬 전략끼리는 서로를 모른다
sorter.setStrategy(new QuickSort());
sorter.sort(data);
// State — 안에서 바뀐다. Draft 는 다음이 Moderation 임을 안다
class Draft implements State {
public void publish(Document d) { d.setState(new Moderation()); }
}
판별 질문
-
① 구현들이 서로를 참조하는가?
- 예 → State (전이를 알아야 하므로)
- 아니오 → Strategy
-
② 런타임에 누가 교체를 결정하는가?
- 외부 클라이언트 → Strategy
- 객체 자신 → State
-
③ 교체 이유가 '정책 선택' 인가 '생명주기 진행' 인가?
- 정책 → Strategy (결제 수단·압축 알고리즘)
- 진행 → State (주문 상태·문서 워크플로)
실무 예로 감을 잡는다
-
Strategy — 결제 수단(카드·계좌·포인트) — 사용자가 고른다, 서로 무관
- 정렬·압축·할인 정책
- Comparator · Spring PasswordEncoder
-
State — 주문 상태(결제대기→배송중→완료) — 시스템이 진행시킨다, 순서가 있다
- TCP 연결 상태 · 문서 승인 흐름
함께 자주 나오는 비교
Template Method vs Strategy
Template Method 상속. 골격은 상위가 고정, 일부만 하위가 채운다 (컴파일 타임)
Strategy 합성. 알고리즘 전체를 통째로 교체한다 (런타임)
면접 함정
- ❌ "다이어그램이 같으니 같은 패턴" → 구조가 아니라 의도와 전환 주체로 구분한다.
- ❌ State를 enum+switch로만 설명 → 상태가 늘 때 모든 메서드를 고쳐야 하는 문제를 못 짚는다.
시그니처에서 차이가 드러난다
// Strategy — 컨텍스트가 전략을 '받는다'. 전략은 컨텍스트를 모른다
void setStrategy(SortStrategy s) { this.strategy = s; } // 외부가 호출
// State — 상태가 컨텍스트를 '받아서 바꾼다'
public void publish(Document d) { d.setState(new Moderation()); }
State 구현은 컨텍스트를 인자로 받는다 — 전이를 일으켜야 하기 때문이다.
사례로 판별해 보기
"할인 정책을 회원 등급에 따라 바꾼다" 밖에서 정해지고 정책끼리 무관 → Strategy
"주문이 결제되면 배송 준비로 넘어간다" 순서가 있고 다음이 정해져 있다 → State
"캐릭터가 체력에 따라 행동이 바뀐다" 자신의 상태 변화가 행동을 바꾼다 → State
"압축 방식을 설정에서 고른다" 외부 선택, 방식끼리 무관 → Strategy
왜 이걸 묻는가
구조가 같은 두 패턴을 구분하려면 클래스 다이어그램이 아니라 의도를 봐야 한다는 것을 아는지 확인하는 질문이다. GoF도 패턴을 목적(생성·구조·행위)으로 분류했지 구조로 분류하지 않았다.