목적
객체의 내부 상태가 바뀔 때 객체의 동작을 변경할 수 있도록 함.
객체는 자신의 클래스를 바꾸는 것 처럼 보임.
요소
문제 : 상태가 여러개 있고, 이를 if 문으로 통제함
해결 : 상태를 한 곳에서 관리
결과 : 변경 최소화
정의
A상태의 handle과 B상태의 handle의 동작이 다르다. -> 상태가 다르면 객체의 동작이 다름
뽑기 기계 구현
뽑기 기계는 4 가지의 상태(매진, 동전없음, 동전있음, 판매)가 있고,
다음의 4 가지 메소드(동전 투입, 반환, 손잡이 돌림, 알맹이 내보냄)가 있다.
상태 패턴을 사용하지 않고 이를 구현하려면 메소드마다 state에 대한 조건문을 구현해야 한다. (4*4 = 16가지를 구현)
만약 state가 추가된다면 조건문을 모든 메소드에 추가해야 된다 -> 문제점
상태 패턴을 이용한 뽑기 기계
상태마다 클래스를 구현하고 뽑기기계는 이 상태 객체를 갈아끼우면서 동작한다.
각 클래스의 메소드는 상태마다 알맞게 구현한다.
새로운 상태가 추가되면 그 상태와 연관된 클래스들만 수정하면 된다.
뽑기기계 클래스
public class GumballMachine {
State soldOutState;
State noQuarterState;
State hasQuarterState;
State soldState;
State state;
int count = 0;
public GumballMachine(int numberGumballs) {
soldOutState = new SoldOutState(this);
noQuarterState = new NoQuarterState(this);
hasQuarterState = new HasQuarterState(this);
soldState = new SoldState(this);
state = soldOutState;
this.count = numberGumballs;
if (numberGumballs > 0) {
state = noQuarterState;
}
}
public void insertQuarter() {
state.insertQuarter();
}
public void ejectQuarter() {
state.ejectQuarter();
}
public void turnCrank() {
state.turnCrank();
state.dispense();
}
public void setState(State state) {
this.state = state;
}
... // 상태 객체를 반환하는 메소드들 getHasQuarterState(), getSoldState(), ...
}
상태 클래스들
메소드가 뽑기 기계의 상태를 바꾸도록 구현 - insertQuater()를 실행하면 HasQuater 상태로 기계를 바꿈 -> 기계의 메소드 내용이 바뀜
// 동전 없음 상태
public class NoQuarterState implements State {
GumballMachine gumballMachine;
public NoQuarterState(GumballMachine gbMachine) {
gumballMachine = gbMachine;
}
public void insertQuarter() {
System.out.println("동전을 넣으셨습니다");
// 동전을 넣은 상태로 변경
gumballMachine.setState(gumballMachine.getHasQuarterState());
}
public void ejectQuarter() {
System.out.println("동전을 넣어주세요");
}
public void turnCrank(){
System.out.println("동전을 넣어주세요");
}
public void dispense(){
System.out.println("동전을 넣어주세요");
}
}
// 동전 있음 상태
public class HasQuarterState implements State {
GumballMachine gumballMachine;
public HasQuarterState(GumballMachine gbMachine) {
gumballMachine = gbMachine;
}
public void insertQuarter() {
System.out.println("동전은 한 개만 넣어주세요");
}
public void ejectQuarter() {
System.out.println("동전이 반환됩니다");
gumballMachine.setState(gumballMachine.getNoQuarterState());
}
public void turnCrank() {
System.out.println("손잡이를 돌리셨습니다");
gumballMachine.setState(gumballMachine.getSoldState());
}
public void dispense() {
System.out.println("알맹이가 나갈 수 없습니다");
}
}
// 판매 상태
public class SoldState implements State {
GumballMachine gumballMachine;
public SoldState(GumballMachine gbMachine) {
gumballMachine = gbMachine;
}
public void insertQuarter() {
System.out.println("잠깐만 기다려 주세요. 알맹이가 나가고 있습니다");
}
public void ejectQuarter() {
System.out.println("이미 알맹이를 뽑으셨습니다");
}
public void turnCrank() {
System.out.println("손잡이는 한 번만 돌려주세요");
}
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());
}
}
}
뽑기 기계를 사용하는 메인 메소드
public static void main(String[] args) {
GumballMachine gumballMachine = new GumballMachine(5);
System.out.println(gumballMachine);
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
}
'컴퓨터과학 > 디자인패턴' 카테고리의 다른 글
[디자인패턴] MVC 패턴 (0) | 2021.12.12 |
---|---|
[디자인패턴] 템플릿 메소드 패턴 (Tempalate Method Pattern) (0) | 2021.12.11 |
[디자인패턴] 커멘드 패턴 (Command Pattern) (0) | 2021.12.06 |
[디자인패턴] 퍼사드 패턴 (Facade Pattern) (0) | 2021.12.05 |
[디자인패턴] 어댑터 패턴 (Adapter Pattern) (0) | 2021.12.05 |
댓글