디자인 패턴 : 상태 패턴

DanChu 🌟·2022년 7월 27일
0
  • 객체 내부 상태 변경에 따라 객체의 행동이 달라지는 패턴
    - 객체는 마치 자신의 클래스를 바꾸는 것처럼 보임
    - 상태에 특화된 행동들을 분리해 낼 수 있으며, 새로운 행동을 추가하더라도 다른 행동에 영향을 주지 않음
  • state 패턴으로 리팩토링 하는 주 목적은 상태 전이를 위한 조건 로직이 지나치게 복잡한 경우 이를 해소하기 위함
Context

객체의 상태를 정의하는 데 사용되는 메소드를 정의하는 인터페이스

State

상태에 따른 동작을 정의하는 인터페이스

ConcreteState

State에서 정의된 메소드를 구현하는 클래스


상태 패턴의 예시

동전을 투입하면 티켓을 뽑을 수 있는 자판기

자판기의 상태:

1) 동전이 없는 상태

  • 동전 투입을 기다림
  • 티켓을 출력 불가능
  • 동전 받으면 동전 투입 상태로 바뀜

2) 동전이 투입 된 상태

  • 티켓을 뽑기 가능
  • 동전을 더 넣어도 상태가 바뀌지 않음
  • 티켓을 뽑으면 동전이 없는 상태로 바뀜

state

public interface State {
  void insertCoin();

  void printTicket();
}

동전이 없는 상태

class CoinState implements State {
  private final TicketMachine ticketMachine;

  CoinState(TicketMachine ticketMachine) {
    this.ticketMachine = ticketMachine;
  }

  @Override
  public void insertCoin() {
    System.out.println("이미 동전이 들어있습니다.");
  }

  @Override
  public void printTicket() {
    // 티켓을 출력하고, 동전을 동전 저장소에 추가한 다음, 동전이 없는 상태로 이동한다.
    TicketPrinter.print();
    CoinRepository.add(1);
    ticketMachine.setState(ticketMachine.getNoCoinState());
  }
}

동전이 투입 된 상태

class NoCoinState implements State {
  TicketMachine ticketMachine;

  NoCoinState(TicketMachine ticketMachine) {
    this.ticketMachine = ticketMachine;
  }

  @Override
  public void insertCoin() {
    // 동전을 넣었다면 동전이 있는 상태로 이동한다.
    ticketMachine.setState(ticketMachine.getCoinState());
  }

  @Override
  public void printTicket() {
    System.out.println("동전이 없습니다. 동전을 넣어주세요.");
  }
}

context : 티켓 자판기

public class TicketMachine {
  final State noCoinState;
  final State coinState;
  private State currentState;

  public TicketMachine() {
    this.noCoinState = new NoCoinState(this);
    this.coinState = new CoinState(this);

    this.currentState = noCoinState;
  }

  public void insertCoin() {
    currentState.insertCoin();
  }

  public void setState(State newState) {
    this.currentState = newState;
  }

  public State getCoinState() {
    return coinState;
  }

  public State getNoCoinState() {
    return noCoinState;
  }
}

상태 패턴의 장단점

장점

  • 하나의 객체에 대한 여러 동작을 구현해야할 때, 상태 객체만 수정 -> 동작의 추가, 삭제, 수정이 간단해짐
  • 상태 패턴을 사용하면 객체의 상태에 따른 조건문이 줄어듦 -> 코드 간결, 가독성 높아짐

단점

  • 상태에 따른 조건문을 대신한 상태 객체가 증가 -> 관리해야 할 클래스 수가 증가

상태 패턴 vs. 전략 패턴 (공통점과 차이점)

공통점

  • 인터페이스 사용으로 Concrete Class를 캡슐화
    - Context Class 영향을 받지 않고 유연한 변경에 대처가 가능

상태 패턴

한 번 인스턴스 생성 후, 상태를 바꾸는 경우가 빈번할 때 사용

전략 패턴

한 번 인스턴스 생성 후에는 상태가 거의 바뀌지 않는 경우에 사용






references

0개의 댓글