UML
실제 적용 UML
- 공통 STATE 인터페이스를 사용하고 모든 상태를 캡슐화를 통해서 관리한다.
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("동전은 한 개만 넣어주세요.");
} else if (state == NO_QUARTER) {
state = HAS_QUARTER;
System.out.println("동전을 넣으셨습니다.");
} else if (state == SOLD_OUT) {
System.out.println("매진되었습니다. 다음 기회에 이용해주세요.");
} else if (state == SOLD) {
System.out.println("잠깐만 기다려 주세요. 알멩이가 나가고 있습니다.");
}
}
//동전 반환
public void ejectQuarter() {
if (state == HAS_QUARTER) {
System.out.println("동전이 반환됩니다.");
state = NO_QUARTER;
} else if (state == NO_QUARTER) {
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_QUARTER) {
System.out.println("동전을 넣어주세요");
} else if (state == SOLD_OUT) {
System.out.println("매진되었습니다");
} else if (state == HAS_QUARTER) {
System.out.println("손잡이를 돌리셨습니다.");
state = SOLD;
dispense();
}
}
//방출
public void dispense() {
if (state == SOLD) {
System.out.println("알멩이가 나가고 있습니다.");
count = count - 1;
if (count == 0) {
System.out.println("더 이상 알멩이가 없습니다.");
state = SOLD_OUT;
} else {
state = NO_QUARTER;
}
} else if (state == NO_QUARTER) {
System.out.println("동전을 넣어주세요");
} else if (state == SOLD_OUT) {
System.out.println("매진입니다");
} else if (state == HAS_QUARTER) {
System.out.println("알멩이가 나갈 수 없습니다.");
}
}
@Override
public String toString() {
return "GumballMachine{" +
"state=" + state +
", count=" + count +
'}';
}
}
개선 코드
디렉토리 구조
GumballMachine
public class GumballMachine {
State soldOutState;
State noQuarterState;
State hasQuarterState;
State soldState;
State winnerState;
State state = soldOutState;
int count = 0;
public GumballMachine(int numberGumballs) {
soldOutState = new SoldOutState(this);
noQuarterState = new NoQuarterState(this);
hasQuarterState = new HasQuarterState(this);
soldState = new SoldState(this);
this.count = numberGumballs;
if ( numberGumballs > 0 ) {
state = noQuarterState;
}
}
public void insertQuarter() {
state.insertQuarter();
}
public void ejectQuarter() {
state.ejectQuarter();
}
public void tumCrank() {
state.tumCrank();
}
public void dispense() {
state.dispense();
}
void releaseBall() {
System.out.println("A gumball comes rolling out the slot...");
if (count != 0) {
count = count - 1;
}
}
}
State Interface
public interface State {
void insertQuarter();
void ejectQuarter();
void tumCrank();
void dispense();
}
HasQuarterState
public class HasQuarterState implements State{
GumballMachine gumballMachine;
public HasQuarterState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
System.out.println("동전은 한 개만 넣어주세요.");
}
@Override
public void ejectQuarter() {
System.out.println("동전이 반환됩니다");
gumballMachine.setState(gumballMachine.getNoQuarterState());
}
@Override
public void tumCrank() {
System.out.println("손잡이를 돌리셨습니다");
gumballMachine.setState(gumballMachine.getSoldState());
}
@Override
public void dispense() {
System.out.println("알멩이가 나갈 수 없습니다.");
}
NoQuarterState
public class NoQuarterState implements State{
GumballMachine gumballMachine;
public NoQuarterState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
System.out.println("동전을 넣으셨습니다.");
gumballMachine.setState(gumballMachine.getHasQuarterState());
}
@Override
public void ejectQuarter() {
System.out.println("동전을 넣어주세요");
}
@Override
public void tumCrank() {
System.out.println("동전을 넣어주세요");
}
@Override
public void dispense() {
System.out.println("동전을 넣어주세요");
}
}
SoldOutState
public class SoldOutState implements State{
GumballMachine gumballMachine;
public SoldOutState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
System.out.println("동전을 넣으셨습니다.");
gumballMachine.setState(gumballMachine.getHasQuarterState());
}
@Override
public void ejectQuarter() {
System.out.println("동전을 넣어주세요");
}
@Override
public void tumCrank() {
System.out.println("동전을 넣어주세요");
}
@Override
public void dispense() {
System.out.println("동전을 넣어주세요");
}
}
SoldState
public class SoldState implements State{
GumballMachine gumballMachine;
public SoldState(GumballMachine gumballMachine) {
this.gumballMachine = gumballMachine;
}
@Override
public void insertQuarter() {
System.out.println("잠시만 기다려주세요. 지금 뽑기가 진행중 입니다");
}
@Override
public void ejectQuarter() {
System.out.println("이미 알멩이를 뽑으셨습니다");
}
@Override
public void tumCrank() {
System.out.println("손잡이는 한 번만 돌려주세요");
}
@Override
public void dispense() {
gumballMachine.releaseBall();
if (gumballMachine.getCount() > 0) {
gumballMachine.setState(gumballMachine.getNoQuarterState());
} else {
System.out.println("Oops, out of gumballs");
gumballMachine.setState(gumballMachine.getSoldOutState());
}
}
}
GumballMachineTest
public class GumballMachineTest {
public static void main(String[] args) {
GumballMachine gumballMachine = new GumballMachine(5);
System.out.println(gumballMachine);
gumballMachine.insertQuarter();
gumballMachine.tumCrank();
System.out.println(gumballMachine);
gumballMachine.insertQuarter();
gumballMachine.tumCrank();
gumballMachine.insertQuarter();
gumballMachine.tumCrank();
System.out.println(gumballMachine);
gumballMachine.releaseBall();
System.out.println(gumballMachine);
}
}