State 패턴

강한친구·2022년 4월 16일
0

OOP Desing Pattern

목록 보기
14/15

뽑기기계

package statepattern;

public class GumballMachine {
    final static int SOLD_OUT = 0;
    final static int NO_QUARTER = 1;
    final static int HAS_QUARTER = 2;
    final static int SOLD = 3;

    int state = SOLD_OUT;
    int count = 0;


    public GumballMachine(int count) {
        this.count = count;
        if (count > 0) {
            state = NO_QUARTER;
        }
    }

    public void insertQuarter() {
        if (state == HAS_QUARTER) {
            System.out.println("One Coin only");
        } else if (state == NO_QUARTER) {
            state = HAS_QUARTER;
        } else if (state == SOLD_OUT) {
            System.out.println("Sold out");
        } else if (state == SOLD) {
            System.out.println("Wait, the ball will soon be yours");
        }
    }

    public void ejectQuarter() {
        if (state == HAS_QUARTER) {
            System.out.println("Returning coin");
            state = NO_QUARTER;
        } else if (state == NO_QUARTER) {
            System.out.println("No Quarter to return");
        } else if (state == SOLD_OUT) {
            System.out.println("You did not insert a token");
        } else if (state == SOLD) {
            System.out.println("You already bought a ball");
        }
    }

    public void turnCrank() {
        if (state == HAS_QUARTER) {
            System.out.println("Crank turned");
            state = SOLD;
            dispense();
            state = NO_QUARTER;
        } else if (state == NO_QUARTER) {
            System.out.println("No Quarter to turn Crank");
        } else if (state == SOLD_OUT) {
            System.out.println("Sorry, SoldOut");
        } else if (state == SOLD) {
            System.out.println("You already bought a ball");
        }
    }

    private void dispense() {
        if (state == SOLD) {
            System.out.println("Ball is being dispensed");
            count -= 1;
            if (count == 0) {
                System.out.println("No balls left");
                state = SOLD_OUT;
            } else {
                state = NO_QUARTER;
            }
        } else if (state == NO_QUARTER) {
            System.out.println("Insert a Coin");
        } else if (state == SOLD_OUT) {
            System.out.println("Sold Out");
        } else if (state == HAS_QUARTER) {
            System.out.println("Ball Stuck");
        }
    }
}

이런 구조를 가진 뽑기기계가 있다고 하자.

지금 이 코드는, 하나의 클래스에서 구현부터 처리까지 전부하고있는 구조이다.

스테이트 패턴의 적용

이러한 뽑기 기계를 운영하던중 10개중 한번꼴로 하나가 더 나오는 코드를 추가해달라는 요청이 들어왔다.

지금 이 코드는, 변경되는 부분을 캡슐화 하라는 가장 기본적인 원칙이 지켜지지 않은 상태이다. 따라서 새로운 디자인을 추가해야한다.

  1. 모든 행동메소드를 담은 인터페이스를 정의
  2. 각 상태별로 행동이 어떤 결과를 나타내는지 보여주는 state 인터페이스 정의
  3. 상태를 전부 위임

스테이트 패턴이란 즉, 객체 내부의 상태가 변함에 따라서 객체의 행동을 바꾸고 마치 클래스의 전환이 일어난것 같은 효과를 얻을 수 있는 방식이다.

변경

우선 WinnerState를 처리하는 Class를 만들어야한다. 그리고 HasToken 상태에서 Winner를 10% 확률로 만들어주는 코드를 짜야한다.

전체 코드

0개의 댓글