개발/디자인패턴

[Java][디자인 패턴] 20. 상태 패턴 (State Pattern)

nova_dev 2022. 3. 25. 00:00
반응형

디자인패턴
[Java][디자인 패턴] 20. 상태 패턴 (State Pattern)

상태 패턴은 조건에 따른 별개의 동작을 제어문으로 사용하지 않고 대신 객체를 캡슐화하여 독립된 동작으로 구분한다.

 

 상태 패턴이란?

  • 각각의 함수 형태로 구별하는 것과 달리 객체로 동작을 분리한다.
  • 객체의 상태에 따라 위임하는 객체를 변경한다.
  • 상태 패턴에서는 함수 형태가 아니라 서브 클래스 형태로 분리한다.
  • 각각의 상태를 객체로 캡슐화하기 때문에 클래스 파일이 늘어난다는 단점이 있으나 상태 패턴을 이용하지 않고 수많은 조건문을 사용하는 것보다는 유연하게 확장할 수 있다.
  • 상태 패턴은 행동 패턴으로 분류되고 객체 내부 상태에 따른 동작 객체를 결정한다.
  • 상태별로 분리된 동작 객체는 독립적이며, 각 상태값에 따라 국지화된 객체 행위를 위임한다.

 

 

 

 

 상태 패턴 구조

  • State
    • 상태 인터페이스
  • ConcreteState
    • 상태의 구체화 클래스
  • Context
    • 상태 값을 가지고 상태 값에 따른 동작을 수행하는 클래스

 상태 패턴 코드

1. State 인터페이스 (PowerState)

public interface PowerState {
    PowerState button();
}

2. State 인터페이스를 구체화한 클래스 (On, Off Class)

public class On implements PowerState {
    @Override
    public PowerState button() {
        System.out.println("전원이 꺼졌습니다.");
        return new Off();
    }
}
public class Off implements PowerState {
    @Override
    public PowerState button() {
        System.out.println("전원이 켜졌습니다.");
        return new On();
    }
}

3. Context 클래스 (Radio, TV)

public class Radio {
    private PowerState powerState;

    public Radio() {
        System.out.println(this.getClass().getSimpleName());
        this.powerState = new Off();
    }

    public void button() {
        powerState = powerState.button();
    }
}
public class TV {
    private PowerState state;

    public TV() {
        System.out.println(this.getClass().getSimpleName());
        this.state = new Off();
    }

    public void button() {
        state = state.button();
    }
}

4. 테스트코드

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

class TVTest {
    @Test
    @DisplayName("TV 테스트")
    void tvTest() {
        TV tv = new TV();
        tv.button();
        tv.button();
    }
}

 

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

class RadioTest {
    @Test
    @DisplayName("라디오 테스트")
    public void radioTest() {
        Radio radio = new Radio();
        radio.button();
        radio.button();
    }
}

 상태 패턴의 장점

장점

  • 구조화
    • 상태 패턴은 거대한 구조의 코드를 구조화하는데 유용함

 

  • 런타임
    • 런타임으로 위임 객체를 변경해 동적으로 행동을 변화
  • 확장성
    • 상태 값에 다라 행동을 위임함으로써 동작을 간편하게 확장 가능
  • 변화
    • 실제 클래스가 변경되는 것이 아니라 구성에 따라서 상태 객체가 변경됨

 상태 패턴 vs 전략 패턴

둘다 런타임으로 객체를 위임해 동작을 변경한다는 공통점을 가지고 있음.

  • 전략 패턴
    • 위임된 객체를 알고리즘으로 생각
    • 객체의 상태값에 관심이 없고, 알고리즘을 교체하고 동작을 변경하는 것만 생각
    • 객체를 이용해 적용 알고리즘을 변경
  • 상태 패턴
    • 위임된 객체를 상태값의 처리로 생각
    • 동작하는 객체의 변경이 상태에 따라 달라짐
    • 이벤트로 발생하는 상태에 따라 객체를 변경

 

 Github 코드

Github 예제 코드 링크

Github 예제 테스트 코드 링크

참고 자료

 

 

 

 

 

반응형