[디자인패턴] State

Judy·2023년 1월 24일
0

디자인패턴

목록 보기
10/11
post-thumbnail

State

Behavior Pattern

개체의 상태가 변경될 때 개체의 동작을 변경할 수 있도록 하는 패턴


문제

State 패턴은 Finite-State Machine과 밀접한 관련이 있습니다.

주요 아이디어는 특정 순간에 프로그램이 가질 수 있는 유한한 상태가 있고, 고유한 상태에서 프로그램은 다르게 동작한다는 것입니다. 프로그램은 즉시 다른 상태로 전환할 수 있지만 현재 상태에 따라 전환되지 않을 수 있습니다.

이러한 접근 방식을 개체에 적용할 수 있습니다. Document라는 클래스가 있을 때 개체는 초안, 조정, 게시됨 세 가지 상태를 가질 수 있고, 해당 상태에 따라 게시 방법은 다를 수 있습니다.

State Machine은 일반적으로 ifswitch 같은 조건문을 사용하여 현재 상태에 따라 적절한 동작을 선택합니다. 보통 이런 "State"는 단지 개체의 필드 값일 뿐입니다.

조건에 기반한 시스템은 더 많은 상태와 동작이 추가되면 각 메서드에 구현된 모든 조건문을 수정해야 합니다. 또한 상태 전환 논리를 변경하면 모든 메서드의 조건을 변경해야 하므로 유지 관리가 매우 어렵습니다.

해결

State 패턴은 가능한 모든 상태를 클래스로 만들고 상태별 동작을 클래스로 추출합니다.

자체적으로 동작을 구현하는 대신 context라 하는 개체의 현재 상태를 가지는 개체에 대한 참조를 가지고 모든 상태 관련 작업을 해당 개체에게 위임합니다.

상태를 변경하려면 active 상태 개체를 새로운 상태를 가지는 다른 개체로 변경합니다. 모든 상태 클래스는 동일한 인터페이스를 따르고 context가 해당 인터페이스를 통해 작동할 경우 가능합니다.

이러한 구조는 Strategy 패턴과 비슷해 보일 수 있지만 State 패턴은 특정 상태는 서로를 인식하고 다른 성태로 전환할 수 있다는 점에서 차이가 있습니다.

현실 예시

스마트폰의 버튼과 스위치는 장치의 현재 상태에 따라 다르게 동작합니다.

  • 잠금 해제 상태 + 버튼 누르기 -> 다양한 기능 실행
  • 잠금 상태 + 버튼 누르기 -> 잠금 해제 화면으로 이동
  • 충전 부족 상태 + 버튼 누르기 -> 충전 화면 나타내기

구조

1. Context

  • 구제척인 상태 객체의 참조를 필드로 가짐
  • State 인터페이스를 통해 상태 개체와 통신
  • 새 상태를 전달하기 위해 setter를 노출

2. State Interface

  • 상태별 메서드를 선언

3. Concrete State

  • 상태별 메서드에 대한 자체 구현을 제공
  • 여러 상태에서 유사한 코드를 제공하는 경우 코드의 중복을 방지하기 위해 일부 공통 동작을 캡슐화하는 중간 추상 클래스를 제공할 수도 있음
  • Context 개체에 대한 역참조를 가져 필요한 정보를 가져오고 상태 전환을 할 수도 있음

적용

💡 현재 상태에 따라 다르게 동작하는 개체이며, 상태 수가 많고, 상태별 코드가 자주 변경될 때
💡 필드의 현재 값에 따라 동작 방식을 변경하는 대규모 조건문을 가졌을 때
💡 조건 기반으로 유사한 상태 및 전환에 따른 중복 코드가 많은 경우

구현 방법

  1. Context로 사용할 클래스 결정
    • 이미 상태와 관련된 코드가 있는 경우 기존 클래스를 사용
  2. State Interface 선언
    • Context의 모든 메서드가 아닌 상태별 동작을 포함하는 메서드만 대상
  3. Concrete State 구현
    • 상태에 따른 동작이 private 필드에 종속된 경우
      -> public으로 변경하기
      or 해당 메서드를 Context에서 public으로 변경하고 State에서 호출하기
      or State 클래스를 Nested로 구현
  4. Context 클래스에서 State Interface를 참조하는 setter 추가
  5. Context 메서드에서 빈 상태 조건을 상태 개체의 해당 메서드 호출로 변경
  6. Context의 상태를 전환하려면 상태 클래스 중 하나의 인스턴스를 생성해서 Context에 전달
    • 이 작업이 수행될 때마다 인스턴스화하는 구체적인 상태에 종속

장단점

✅ 장점

  • SRP - 특정 상태와 관련된 코드를 별도 클래스로 구성
  • OCP - 기존 상태 클래스와 Context 클래스를 변경하지 않고 새로운 상태 도입 가능
  • 부피가 큰 조건문을 제거하고 코드를 단순화

❎ 단점

  • 상태가 몇 개만 있거나 거의 변경되지 않는 경우에 패턴을 적용하는 것은 과도할 수 있음




State Pattern

profile
iOS Developer

0개의 댓글