스테이트 패턴(State Pattern)
1. 목적
객체의 내부 상태가 바뀔 때 객체의 동작을 변경할 수 있도록 한다.
객체는 자신의 클래스를 바꾸는 것처럼 보인다.
구분 | 설명 |
State(상태) | 시점에 따라 특정 상태에 있어야 한다. 처음에 가지게 되는 초기상태(state) 또는 상황에 따라 여러 상태 가운데 한 상태를 가질 수 있다 |
Transition(전이) | 외부 입력에 따라 가능한 상태로 전환 |
예
- 게임 캐릭터: 걷는 상태, 뛰는 상태, 멈춘 상태
- 가전 제품: on, off, sleep
- 지하철 개찰구: 열림, 잠금
2. 요소
요소 | 설명 |
이름 | 스테이트(State) |
문제 | 상태(state)가 여러 개 있고, if문으로 상태를 통제 |
해결방안 | 상태를 한 곳에서 관리 |
결과 | 변경 최소화 |
public class Main {
public static void main(String[] args) {
CalcV1 calcv1 = new CalcV1();
boolean run = true;
while (run) {
run = calcv1.run();
}
}
}
import java.util.Scanner;
public class CalcV1 {
// private enum STATES { STATE_START, STATE_FIRST_OPERAND, STATE_SECOND_OPERAND, STATE_OPERATOR };
Scanner scanner;
String inputStr;
int operand1; // 첫 번째 피 연산자값 저장
int operand2; // 두 번째 피 연산자값 저장
// STATES state;
State state;
char operator; // 사칙 연산자 저장
State stateFirstOperand;
State stateOperator;
State stateSecondOperand;
State stateStart;
public CalcV1() {
scanner = new Scanner(System.in); // Create a Scanner object
// state = STATES.STATE_START;
stateFirstOperand = new StateFirstOperand(this);
stateOperator = new StateOperator(this);
stateSecondOperand = new StateSecondOperand(this);
stateStart = new StateStart(this);
state = stateStart;
}
public void setState(State state) {
this.state = state;
}
public void setOperand1(int num1) {
operand1 = num1;
}
public void setOperand2(int num2) {
operand2 = num2;
}
public void setOperator(char op) {
operator = op;
}
public State getFirstOperandState() {
return stateFirstOperand;
}
public State getOperatorState() {
return stateOperator;
}
public State getStartState() {
return stateStart;
}
public State getSecondOperandState() {
return stateSecondOperand;
}
public String getInput(String s) {
System.out.println(s);
return scanner.next();
}
public void printOutResult() {
switch (operator) {
case '+':
System.out.printf("%d + %d = %d\n", operand1, operand2, operand1 + operand2);
break;
case '-':
System.out.printf("%d - %d = %d\n", operand1, operand2, operand1 - operand2);
break;
case '*':
System.out.printf("%d * %d = %d\n", operand1, operand2, operand1 * operand2);
break;
case '/':
System.out.printf("%d / %d = %d\n", operand1, operand2, operand1 / operand2);
break;
}
}
/* 정수가 입력되었을 때 처리 */
public void processNumber(String ch) {
state.processNumber(Integer.parseInt(ch));
// if (state == STATES.STATE_START) {
// operand1 = Integer.parseInt(ch);
// state = STATES.STATE_FIRST_OPERAND;
// }
// else if (state == STATES.STATE_OPERATOR) {
// operand2 = Integer.parseInt(ch);
// state = STATES.STATE_SECOND_OPERAND;
// }
}
/* 사칙 연산자 혹은 = 연산자 처리 */
public void processOperator(char ch) {
state.processOperator(ch);
// if (state == STATES.STATE_FIRST_OPERAND) {
// state = STATES.STATE_OPERATOR;
// operator = ch;
// }
// else if (state == STATES.STATE_SECOND_OPERAND) {
// if (ch == '=') {
// printOutResult();
// state = STATES.STATE_START;
// }
// }
}
/* 프로그램의 주 로직을 담당하는 함수
사용자 입력을 기다렸다가 q 또는 Q가 입력되면 종료
그렇지 않으면 정수가 입력되었는지 혹은 연산자가 입력되었는지에 따라 processNumber 또는 processOperator 함수를 호출
*/
public boolean run() {
inputStr = getInput("정수 또는 +,-,*,/,= 기호 중 한 개를 입력하세요");
char ch = inputStr.charAt(0);
if (ch == 'q' || ch == 'Q') { // q를 입력하면 프로그램 종료
return false;
}
else if (ch >= '0' && ch <= '9') { // 정수가 입력되면
processNumber(inputStr);
}
else if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '=') { // 연산자 처리
processOperator(ch);
}
return true;
}
}
public interface State {
default void processNumber(int num) {
System.out.println("processNumber: Invalid operation");
}
default void processOperator(char op) {
System.out.println("processOperator: Invalid operation");
}
}
public class StateFirstOperand implements State {
CalcV1 calcV1;
public StateFirstOperand(CalcV1 calcV1) {
this.calcV1 = calcV1;
}
@Override
public void processOperator(char op) {
calcV1.setOperator(op);
calcV1.setState(calcV1.getOperatorState());
}
}
public class StateSecondOperand implements State {
CalcV1 calcV1;
public StateSecondOperand(CalcV1 calcV1) {
this.calcV1 = calcV1;
}
@Override
public void processOperator(char op) {
if (op == '=') {
calcV1.printOutResult();
calcV1.setState(calcV1.getStartState());
}
}
}
public class StateOperator implements State {
CalcV1 calcV1;
public StateOperator(CalcV1 calcV1) {
this.calcV1 = calcV1;
}
@Override
public void processNumber(int num) {
calcV1.setOperand2(num);
calcV1.setState(calcV1.getSecondOperandState());
}
}
public class StateStart implements State {
CalcV1 calcV1;
public StateStart(CalcV1 calcV1) {
this.calcV1 = calcV1;
}
@Override
public void processNumber(int num) {
calcV1.setOperand1(num);
calcV1.setState(calcV1.getFirstOperandState());
}
}
'Java > 고급객체지향' 카테고리의 다른 글
고급객체지향 프로그래밍 - MVC 패턴(Model-view-Controller Pattern) (0) | 2021.12.12 |
---|---|
고급객체지향 프로그래밍 - 템플릿 메소드 패턴(Template Method pattern) (0) | 2021.12.12 |
고급객체지향 프로그래밍 - 커맨드 패턴(Command Pattern) (0) | 2021.12.12 |
고급객체지향 프로그래밍 - 퍼사드 패턴(Facade Pattern) (0) | 2021.12.12 |
고급객체지향 프로그래밍 - 어댑터 패턴(Adapter Pattern) (0) | 2021.12.12 |