Open j03y14 opened 5 months ago
동전 없음 → (동전넣기) → 동전 있음 → (동전반환) → 동전 없음
동전 없음 → (동전넣기) → 동전 있음 → (손잡이 돌림) → 알맹이 반환 → 알맹이 = 0 → 알맹이 없음
4가지 상태와 4가지 행동이 정의되었다 + 전환의 종류는 5가지
// 상태 정의
const SOLD_OUT = 0;
const NO_QUARTER = 1;
const HAS_QUARTER = 2;
const SOLD = 3;
const state = SOLD_OUT;
상태 기계 역할 클래스
class insertQuarter() {
if (state === HAS-QUARTER){
console.log('동전은 한개만 넣어주세요');
} else if(state === NO_QUARTER){
state = HAS_QUARTER;
console.log('동전이 투입되었습니다');
} else if(state === SOLD_OUT){
console.log('매진되었습니다.');
} else if(state === SOLD){
console.log('알맹이를 내보냅니다');
}
}
class GumBallMachine(){
SOLD_OUT = 0;
NO_QUARTER = 1;
HAS_QUARTER = 2;
SOLD = 3;
state = SOLD_OUT;
count = 0;
constructor(count){
this.count = count;
if(count > 0){
state = NO_QUARTER;
}
}
insertQuarter() {
if (state === HAS-QUARTER){
console.log('동전은 한개만 넣어주세요');
} else if(state === NO_QUARTER){
state = HAS_QUARTER;
console.log('동전이 투입되었습니다');
} else if(state === SOLD_OUT){
console.log('매진되었습니다.');
} else if(state === SOLD){
console.log('알맹이를 내보냅니다');
}
}
ejectQuarter(){
//...
}
turnCrank(){
//...
}
dispense(){
//...
}
}
const gumballMachine = new GumballMachine(5);
gumballMachine.insertQuarter();
gumballMachine.turnCrank();
gumballMachine.insertQuarter();
gumballMachine.ejectQuarter();
너무 많은 메소드가 변경됨
바뀌는 부분이 캡슐화 되지 않았습니다
상태 전환이 조건문 속에 숨어있어서, 분명하게 드러나지 않습니다.
상태 객체들을 별도의 코드에 넣고, 어떤 행동이 일어날 때 상태 객체에게 필요한 작업을 처리하게 한다.
각 상태별로 행동을 정의해서 클래스에 넣는다
interface State{
insertQuarter();
ejectQuarter();
turnCrank();
dispense();
}
class SoldState: State(){
//...
}
class SoldOutState extends State
class NoQuarterState extends State() {
gumballMachine
constructor(gumballMachine: GumballMachine) {
this.humballMachine = gumballMachine;
}
// state update here
insertQuarter() {
gumballMachine.setState(gumballMachine.getHasQuarterState());
}
ejectQuarter(){
console.log('');
}
turnCrank(){
console.log('');
}
dispense(){
console.log('');
}
}
class HasQuarterState
// new state
class WinnerState
class gumballMachine(){
soldOutState: State;
noQuarterState: State;
hasQuarterState: State;
soldState: State;
state: State
gumballs: number;
constructor(gumballs: number){
soldOutState = new SoldoutState(this);
noQuarterState = new NoQuarterState(this);
hasQuarterState = new HasQuarterState(this);
soldState = new SoldState(this);
this.count = gumballs;
if(gumballs > 0){
state = noQuarterState;
} else {
state = soldOutState;
}
}
insertQuarter() {
state.insertQuarter();
}
ejectQurater() {
state.ejectQuarter();
}
// ...
setState(state) {
this.state = state;
}
}
객체 내부 상태가 바뀜에 따라서 객체의 행동을 바꿀 수 있습니다.
Context객체(gumballMachine) 을 사용합니다.
Context 객체에 수많은 조건문을 넣지 않고 상태 패턴을 쓴다.
이를 통해 상태에 따라 서로 다른 행동을 실행하도록 한다.
상태 패턴은 상태 객체에 행동이 캡슐화 됩니다.
전략 패턴은 클라이언트가 Context 객체에게 어떤 전략을 사용할지 지정합니다.
새로운 state 정의하고, 기존 state에서 해당 state로 변경되는 경우를 찾아 수정해주면 됩니다.
SoldState와 WinnerState를 구분하는 이유는 단일 책임 원칙을 위해서 이다.
이렇게 작동하는 뽑기 기계 프로그램을 만들고 싶다.
10분의 1의 확률로 뽑기가 2개 나오도록 하고싶다. 당첨상태 추가 필요.
당첨 상태가 추가되면 모든 메서드에 당첨 상태를 추가해야한다.
이렇게 되면 생기는 문제점:
바뀌는 부분을 캡슐화 하려면?
상태별 행동을 별도의 클래스에 넣어두고 모든 상태에서 각각 자기가 할 일을 구현하도록 한다. 그리고, 뽑기 기계가 현재 상태를 나타내는 상태에게 작업을 넘기게 한다.
상태 패턴
상태를 별도의 클래스로 캡슐화 한 다음 현재 상태를 나타내는 객체에게 행동을 위임한다.
Q&A
정상성 점검하기
논의해볼만한 점