같은 목적을 가진 여러 알고리즘을 각각 별도 객체(또는 함수)로 빼고, 실행할 때 그중 하나를 골라 끼우는 패턴. 호출하는 쪽은 공통 인터페이스만 안다.
type DiscountStrategy = (price: number) => number
const strategies: Record<string, DiscountStrategy> = {
none: p => p,
member: p => p * 0.9,
coupon: p => Math.max(0, p - 3000),
}
function checkout(price: number, kind: keyof typeof strategies) {
return strategies[kind](price)
}- 새 할인 방식을 추가할 때
checkout을 고치지 않고 전략만 더한다. 확장에 열리고 수정에 닫힌 구조다(SOLID 원칙의 OCP, Open-Closed Principle) - 할인 계산, 정렬 기준, 인증 방식, 렌더링 방식 선택이 전형적인 예다
- 테스트에서 가짜 전략을 넣기 쉽다
- 일급 함수가 있는 언어에서는 위처럼 함수 하나로 충분하다. 인터페이스와 클래스 계층을 갖춘 객체 전략은 상태가 필요하거나 메서드가 여럿일 때만 쓴다
비슷한 것들과의 차이
- 상태 패턴과 구조는 같지만, 전략은 바깥에서 고르고 상태는 객체가 스스로 다음 상태로 바뀐다
- 템플릿 메서드 패턴는 상속으로 단계를 바꾸고, 전략은 합성으로 알고리즘 전체를 바꾼다
- 타입별 switch를 없애는 조건부 로직을 다형성으로 바꾸기의 결과가 전략 구조인 경우가 많다
- 설정 배열에 항목마다
render함수를 두는 설정 기반 UI도 전략 패턴의 응용이다
행동 패턴 전체는 행동 패턴.