Shong Studio의 정보 창고

[디자인 패턴] State Pattern (상태 패턴) - 직관적인 설명 & 예시 본문

디자인 패턴

[디자인 패턴] State Pattern (상태 패턴) - 직관적인 설명 & 예시

Shong Studio 2024. 3. 23. 17:02
728x90
반응형

안녕하세요, Shong Studio입니다.

 

디자인 패턴 중에서 객체의 상태 변화에 따라 객체의 행동이 바뀌어야 할 때 유용하게 사용할 수 있는 "State Pattern"에 대해 살펴보겠습니다.

State Pattern 이란?

State Pattern은 객체의 내부 상태가 변경될 때마다 객체의 행동도 함께 변경되도록 하는 행위 디자인 패턴입니다. 즉, 객체의 상태를 나타내는 클래스 집합과 그 상태에 따른 행동을 캡슐화하는 방식으로, 객체의 상태 변화에 따라 동일한 작업을 다른 방식으로 처리할 수 있게 합니다. 이 패턴을 통해 복잡한 조건 분기 없이 상태에 따른 행동의 변화를 구현할 수 있습니다.

State Pattern을 사용해야 하는 이유는?

  1. 코드의 유지보수성 향상: 상태에 따른 행동이 명확하게 분리되므로, 특정 상태의 로직을 수정할 때 다른 상태의 코드에 영향을 미치지 않습니다.
  2. 조건문의 복잡성 감소: 상태 패턴을 사용하면 복잡한 조건문 대신 상태 객체를 통해 로직을 관리할 수 있어, 코드의 가독성과 관리성이 크게 향상됩니다.
  3. 확장성 증가: 새로운 상태를 추가하고자 할 때 기존 코드를 수정할 필요 없이 새로운 상태 클래스를 추가하기만 하면 됩니다. 이는 개방/폐쇄 원칙을 준수합니다.

State Pattern 구조

State pattern class diagram

구조를 보면 알 수 있듯이 Context에서 State라는 클래스 타입으로 state를 관리하고 있습니다.

changeState를 통해서 state가 변경될때마다 state의 값은 바뀔 것이고,

operation function에서는 단순히 state.operation()만 구현해 놓으면 상태에 따라서 다른 action을 실행하게 될 것입니다.

★★ 만약 위 구조에서 State Pattern을 사용하지 않았다면?? 

Context의 operation 내에서 if, else 조건문을 통해서 아래와 같이 지저분한 코드가 들어가게 될 것입니다.

만약 state마다 취해주는 action이 복잡해지면 지저분한 코드가 될 것이고 requirement가 수정되었을 때 유지 보수에 어려움을 겪을 수 있습니다.

 

if(state == A){

   // action A

} else if(state == B){

  // action B

} else if(state == C){

  // action C

}

 

State Pattern을 어떻게 사용하는지 알아보자

상태 패턴의 전형적인 예로, 껌 자판기를 예제를 구현해보겠습니다.

자판기는 '동전 없음', '동전 있음', '껌 판매됨', '껌 매진' 등의 상태를 가질 수 있습니다.

 

1. State 인터페이스 정의

먼저, 모든 상태가 구현해야 하는 State 인터페이스를 정의합니다.

public interface State {
    void insertCoin();
    void ejectCoin();
    void pressButton();
    void dispense();
}

 

 

2. Concrete State 클래스 구현

각 상태를 나타내는 구체 클래스를 구현합니다. 여기서는 '동전 없음' 상태를 예로 듭니다.

public class NoCoinState implements State {
    GumballMachine gumballMachine;

    public NoCoinState(GumballMachine gumballMachine) {
        this.gumballMachine = gumballMachine;
    }

    @Override
    public void insertCoin() {
        System.out.println("동전을 넣으셨습니다.");
        gumballMachine.setState(gumballMachine.getHasCoinState());
    }

    @Override
    public void ejectCoin() {
        System.out.println("동전을 넣어주세요.");
    }

    @Override
    public void pressButton() {
        System.out.println("동전을 넣어주세요.");
    }

    @Override
    public void dispense() {
        System.out.println("동전을 넣어주세요.");
    }
}

 

public class GumballMachine {
    State noCoinState;
    State hasCoinState;
    State soldState;
    State soldOutState;

    State state = soldOutState;
    int count = 0;

    public GumballMachine(int numberGumballs) {
        noCoinState = new NoCoinState(this);
        hasCoinState = new HasCoinState(this);
        soldState =
(Skip)

 

 

728x90
반응형