dh_0e

[Design Pattern] Behavior Design Patterns III (State Pattern, Strategy Pattern) 본문

Software Analysis & Design/Design Patterns

[Design Pattern] Behavior Design Patterns III (State Pattern, Strategy Pattern)

dh_0e 2025. 11. 25. 12:18

상태 패턴(State Pattern)

  • 객체의 내부 상태가 변경될 때, 객체 스스로가 상태에 따라 행동을 변경할 수 있도록 하는 행동 패턴
  • 상태(State): 객체가 가질 수 있는 어떤 조건이나 상황
  • ex) TV의 상태 ON/OFF에 따라 음량 버튼의 동작 방식이 달라지는 경우

  • 필요한 상황
    • 만약 문서(Document) 클래스가 Draft(초안), Moderation(검토), Published(출판됨)와 같은 여러 상태를 가지고 publish 메서드가 각 상태에 따라 다르게 작동해야 할 때

  • publish 메서드
    • Draft(초안): 문서를 Moderation(검토) 상태로 이동
    • Moderation(검토): 문서를 공개하거나 관리자에게만 공개
    • Published(출판됨): 아무런 작업을 하지 않음

상태 패턴 적용 전 코드

  • 상태 패턴 아이디어
    • 객체의 모든 가능한 상태들에 대해서 새 클래스를 만들고 모든 상태별 행동들을 상태 클래스에서 추출

문서 출판 작업 State Pattern 예시
State Pattern 구조

역할 설명
1. Context State를 가지는 객체. 상태를 나타내는 참조 필드를 가지며, 외부에서 Context의 메서드를 호출하면 현재 상태 객체에 위임
2. State (Interface/Abstract Class) 상태별 메서드를 선언하는 인터페이스 또는 추상 클래스.
3. Concrete State 구체적인 각각의 상태를 클래스로 표현. State 역할로 결정되는 메서드들을 구현하며, Context에 대한 참조를 가지고 있어 상태를 변경하거나 정보를 가져오기도함.

 

ex) 노트북 전원 상태에 따른 동작 설계

  • 노트북 전원 ON 상태에서 전원 버튼을 누르면 전원 OFF 상태로 변경
  • 노트북 전원 OFF 상태에서 전원 버튼을 누르면 전원 ON 상태로 변경
  • 노트북 절전 모드 상태에서 전원 버튼을 누르면 전원 ON 상태로 변경

State Pattern 예시 코드(State, Concrete State)
State Pattern 예시 코드(Context)
State Pattern 예시 코드(Client)

  • 장점
    • SRP 준수: 상태에 따른 동작을 개별 클래스로 옮겨서 관리할 수 있음
    • OCP 준수: 기존 상태 클래스나 컨텍스트를 변경하지 않고 새 상태 도입 가능
    • 상태와 관련된 모든 동작 각각의 상태 클래스에 분산시켜 로직의 복잡도를 줄일 수 있음
    • + 런타임에 객체의 상태를 바꿔줄 수 있음, 상태를 다른 context에 재사용할 수 있음
  • 단점
    • 상태 별로 클래스를 생성하므로 관리해야 하는 클래스 수가 증가
    • 객체에 적용할 상태가 몇가지 밖에 없거나 거의 상태 변경이 이루어지지 않는 경우 패턴 적용이 과할 수 있음
      • ex) 컴퓨터가 켜져있는 상태에서 모든 동작을 그 클래스에게 구현하는 것은 과함

 


 

전략 패턴(Strategy Pattern)

  • 실행 중에 알고리즘(전략)을 선택하여 객체 동작을 실시간으로 바뀌도록 할 수 있게 하는 행동 패턴
  • 전략(Strategy): 일종의 알고리즘, 기능, 동작을 의미

  • 필요한 상황
    • 내비게이션 앱에서 경로를 찾는 기능(도보, 대중교통, 자전거 등)을 설계할 때, 새로운 경로 구축 알고리즘을 추가할 때마다 내비게이터 클래스(Context)가 복잡해지는 것을 방지해야 할 때
      • 첫 번째 버전에서 도로로 된 경로만을 찾을 수 있도록 하면, 차가 없는 사람이 만족할 수 없음
      • 도보, 대중교통, 자전거 등의 경로 옵션을 제공하는 형태로 확장
      • 비행기 등의 새로운 경로 구축 알고리즘을 추가할 때마다 내비게이터 클래스가 복잡해짐
  • 전략 패턴 아이디어
    • 특정 작업은 다양한 방식으로 수행하는 클래스를 선택한 후 모든 알고리즘을 strategy라는 별도의 클래스로 추출

Strategy Pattern 구조 예시
Staregy Pattern 구조

역할 설명
Context 구체적인 전략 중 하나에 대한 참조를 유지. 전략 인터페이스를 통해서만 통신.
Strategy (Interface/Abstract Class) 모든 구상 전략에 공통인 인터페이스를 정의.
Concrete Strategy Context가 사용하는 알고리즘의 다양한 변형들을 구현.
Client 특정 전략 객체를 생성하여 Context에 전달(주입)합니다.

 

ex) Pay Method

Staregy Pattern 예시 코드(Strategy)
Staregy Pattern 예시 코드(Concrete Strategies)
Strategy Pattern 코드 예시(Context, 아이템)
Strategy Pattern(Client)

 

  • JAVA에서 전략 패턴 사용 예시
    • Comparator: 비교 전략을 런타임에 정의하고 변경할 수 있음

  • new Comparator<Integer>()하면 익명 자식 클래스를 만들어서 arrow function처럼 사용한 것
  • 알고리즘을 짜서 넣어주면 요걸 참조하게 되는데 여기에서 알게 모르게 전략패턴을 쓰고있었음
    • Context(문맥): Collections.sort() 메서드
    • Strategy(전략): Comparator 인터페이스
    • Concrete Strategy(구체적 전략): 작성한 익명 자식 클래스

 

  • 장점
    • 런타임(실시간)에 객체 내부에서 사용되는 알고리즘을 교환할 수 있음
    • OCP 준수: 새로운 알고리즘을 추가하더라도 기존 코드에 영향이 없음
    • SRP 준수: 전략 클래스는 단 하나의 알고리즘을 가짐
    • 재사용 가능: 다른 Context에서 전략을 재사용하기 편함
  • 단점
    • 알고리즘이 몇 개밖에 되지 않고 거의 변하지 않는다면 사용이 과함
    • 클라이언트들은 적절한 전략을 선택할 수 있도록 전략 간의 차이점을 알고 있어야 함

 


 

Summary

  • State Pattern vs Strategy Pattern
    • 유사점
      • 클래스 다이어그램이 거의 유사하고, 사용법이 비슷함
        • 이거 다른 패턴도 구분 잘해야 함
      • 둘 다 합성(composition)/집합을 통해 해결함
    • 차이점
      • 초점에 있어서의 차이
        • 상태 패턴: 객체의 상태에 따른 행동 변화에 중점
        • 전략 패턴: 알고리즘의 동적인 교체에 중점
        • 상태는 알고리즘을 가지고 있는 게 아님!
      • 적용 시나리오에 있어서 차이
        • 상태 패턴: 객체가 여러 상태를 가지고 있고, 상태에 따라 행동이 달라야 할 때 사용
        • 전략 패턴:  알고리즘이 독립적으로 정의되어야 하고, 런타임에 교체해야 할 때 사용
      • Concrete 객체가 Context를 참조하는지 차이
        • ConcreteStates: Context를 참조하는 필드를 가지고 있어 필요한 정보를 가져오거나 Context의 상태를 변경함
        • ConcreteStrategy: Context를 참조하지 않고 알고리즘에 관련된 정보만 가지고 있음