관리 메뉴

bright jazz music

상태 패턴 본문

Design Pattern

상태 패턴

bright jazz music 2022. 9. 16. 08:15

상태 패턴은 특정 상태에 따라 행동이 달라지는 객체를 위한 패턴.

쉽게는 리모콘이 예다.

티비의 상태에 따라(켜/꺼)에 따라 버튼이 작동이 다르다.

- 켜: 채널

- 꺼: 채널

 

블로그도 마찬가지,

비공개 상태( 드래프트 상태)일 때의 포스팅은 클릭할 수도 없고 URL을 입력한다고 접근할 수 없다.

 

공개가 되면 다른 사람들이 와서 댓글/조항요도 누를 수 있다.

--> 상태 변경에 따라 특정 오브젝트들의 행동이 바뀌는데,

이를 스테이트 패턴으로 정리할 수 있다.

 

----------------------------

 

전략패턴과 상태패턴은 쌍둥이다.

- 전략패턴은 바꿔 쓸 수 있는 알고리즘을 사용한다.

- 상태패턴은 내부 상태를 바꿈으로써 객체가 행동을 바꿀 수 있도록 한다.

 

 

예를 들어 동전 뽑기 기계

 

두 가지 상태

- 동전 없음(초기상태).

- 동전 있음.

 

동전 없음 ==> 동전 투입 ==> 동전 있음(상태 전환)

 

동전 있음 상태 ==> 손잡이 회전 ==> 알맹이 판매

 

동전 없음 ==> 동전 투입 ==> 동전 있음(상태 전환)

동전 있음 ==> 손잡이 돌림 ==>알맹이 존재 ? 알맹이 판매 : 동전 반환

 

 

초기 디자인

package com.study.study_project.statePattern;

public class GumballMachine {
    //껌 기계 클래스

    // 총 4개의 상태가 존재 : 각 상태마자 유일한 정수 부여
    final static int SOLD_OUT = 0;      //알맹이 매진
    final static int NO_COIN = 1;       //동전 없음
    final static int HAS_COIN = 2;      //동전 있음
    final static int SOLD =3;           // 알맹이 판매

    int state = SOLD_OUT;       //현재 상태를 저장하는 인스턴스 변수
    //최초에는 뽑기 기계에 아무런 알맹이가 없으므로 매진 상태로 설정

    int count = 0; //알맹이 개수

    //행동 4개
    //동전 투입, 동전 반환, 손잡이 회전, 알맹이 내보냄.
    // 이런 행동 실행 시 상태 변환됨. 행동은 해당 클래스의 인터페이스라고 할 수 있다.

    //생성자: 초기 알맹이 개수를 파라미터로 받음.
    public GumballMachine(int count) {
        this.count = count;
        if (count > 0) {
            state = NO_COIN;
            //입력된 알맹이 개수가 0보다 크면 상태가 NO_COIN으로 변환됨. 알맹이는 있지만 동전은 없는 상태.
            // 입력값이 0이면 상태는 여전히 SOLD_OUT
        }
    }

    public void insertCoin() {
        if (state == HAS_COIN) { //동전히 투입되어 있는 경우
            System.out.println("동전은 한 개만 넣어 주세요"); //동전이 이미 들어 있으므로.
        }else if(state == NO_COIN) { //동전히 들어 있지 않은 경우
            state = HAS_COIN;// "동전 있음"으로 상태변경
            System.out.println("동전을 넣으셨습니다.");
        }else if (state == SOLD_OUT) {//매진 상태
            System.out.println("알맹이가가 매진되었습니다.나중에 이용하세요."); //동전 반환
        }else if (state == SOLD){
            System.out.println("알맹이를 내보내고 있습니다.");
        }
    }

    public void ejectCoin(){
        if(state == HAS_COIN){
            System.out.println("동전이 반환됩니다.");
            state = NO_COIN;
        }else if(state == NO_COIN){
            System.out.println("동전이 없습니다. 동전을 넣어주세요.");
        }else if (state == SOLD){
            System.out.println("이미 알맹이를 뽑으셨습니다.");
        }else if (state == SOLD_OUT){
            System.out.println("동전을 넣지 않으셨습니다. 동전이 반환되지 않습니다.");
        }
    }

    public void turnCrank() {
        if (state == SOLD) {
            System.out.println("손잡이는 한 번만 돌려주세요");
        }else if(state == NO_COIN) {
            System.out.println("동전을 넣어 주세요");
        }else  if (state == SOLD_OUT) {
            System.out.println("매진 되었습니다");
        }else if (state == HAS_COIN){
            state = SOLD; //상태를 내보내는 중인 SOLD로 변환
            dispense();
        }
    }

    public void dispense(){
        if (state == SOLD) {
            System.out.println("알맹이를 내보내는 중입니다.");
            count = count - 1; //알맹이 개수 한 개 줄이기
            if (count == 0){
                state = SOLD_OUT; //책에는 상태 변환이 메시지 출력보다 나중에 나온다.
                System.out.println("알맹이가 매진되었습니다.");
            } else { //남은 수량이 0이 아니라면
                state = NO_COIN;
            }
        }else if (state == NO_COIN){ //오류 방지1: 동전이 없는데 dispense()가 호출되어서는 안 된다.
            System.out.println("동전을 넣어 주세요.");
        }else if (state == SOLD_OUT) {//오류 방지2: 매진인데 dispense()가 호출되어서는 안 된다.
            System.out.println("매진입니다.");
        }else if (state == HAS_COIN) {//오류 방지3: 손잡이 안 돌렸는데 dispense()가 호출되어서는 안 된다.
            System.out.println("알맹이를 내보낼 수 없습니다.");
        }
    }


}

 

 

 

 

 

 

 

 

 

 

'Design Pattern' 카테고리의 다른 글

01. Iterator 패턴  (0) 2023.05.31
디자인 패턴 소스 코드  (0) 2022.11.07
Comments