State Pattern이란?

객체의 내부 상태가 바뀔 때 객체의 동작을 변경할 수 있도록 합니다. (객체의 현재 상태에따라 입력 혹은 실행하는 메소드가 다르다.)


코드 요약

▶ Calculator 객체는 StartState, Num1State, OperandState, Num2State총 4가지의 상태를 가집니다. 사용자는 숫자 혹은 연산자를 입력하며 'q'가 입력되면 종료합니다.

1. StartState: 숫자를 입력받고 num1에 저장합니다.

2. Num1State: 연산자를 입력 받고 operand에 저장합니다.

3. OperandState: 숫자를 입력받고 num2에 저장합니다.

4. Num2State: '='을 입력받아 계산을 실행하고 출력합니다. 

 


클래스 다이어그램

 

1. State interface

public interface State {
    default void processNumber(int n){}
    default void processOperator(char ch){}
}

 

2. StartState class

public class StartState implements State{
    private Calculator calculator;

    public StartState(Calculator calculator) {
        this.calculator = calculator;
    }

    @Override
    public void processNumber(int n) {
        calculator.setNum1(n);
        calculator.setState(calculator.getNum1State());
    }
}

3. Num1State

public class Num1State implements State{
    private Calculator calculator;

    public Num1State(Calculator calculator) {
        this.calculator = calculator;
    }

    @Override
    public void processOperator(char ch) {
        calculator.setOperator(ch);
        calculator.setState(calculator.getOperatorState());
    }
}

 

4. OperatorState

public class OperatorState implements State{
    private Calculator calculator;

    public OperatorState(Calculator calculator) {
        this.calculator = calculator;
    }

    @Override
    public void processNumber(int n) {
        calculator.setNum2(n);
        calculator.setState(calculator.getNum2State());

    }
}

 

5. Num2State

public class Num2State implements State{
    private Calculator calculator;

    public Num2State(Calculator calculator) {
        this.calculator = calculator;
    }

    @Override
    public void processOperator(char ch) {
        calculator.printOutResult();
        calculator.setState(calculator.getStartState());
    }
}

 

6. Calculator class

import java.util.*;

public class Calculator {
    Scanner scanner;
    String inputStr;
    int num1;
    int num2;
    State state;
    char operator;
    State startState;
    State num1State;
    State operatorState;
    State num2State;


    public Calculator() {
        this.startState = new StartState(this);
        this.num1State = new Num1State(this);
        this.operatorState = new OperatorState(this);
        this.num2State = new Num2State(this);
        state = startState;
        scanner = new Scanner(System.in);
    }


    public void setNum1(int num1) {
        this.num1 = num1;
    }

    public void setNum2(int num2) {
        this.num2 = num2;
    }

    public void setState(State state) {
        this.state = state;
    }


    public void setOperator(char op) {
        operator = op;
    }

    public State getStartState() {
        return startState;
    }

    public State getNum1State() {
        return num1State;
    }

    public State getOperatorState() {
        return operatorState;
    }

    public State getNum2State() {
        return num2State;
    }

    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", num1, num2, num1 + num2);
                break;

            case '-':
                System.out.printf("%d - %d = %d\n", num1, num2, num1 - num2);
                break;

            case '*':
                System.out.printf("%d * %d = %d\n", num1, num2, num1 * num2);
                break;

            case '/':
                System.out.printf("%d / %d = %d\n", num1, num2, num1 / num2);
                break;
        }
    }


    public void processNumber(String ch) {
        state.processNumber(Integer.parseInt(ch));
    }

    public void processOperator(char ch) {
        state.processOperator(ch);
    }

    public boolean run() {
        inputStr = getInput("정수 또는 +,-,*,/,= 기호 중 한 개를 입력하세요");
        char ch = inputStr.charAt(0);
        if (ch == 'q' || ch == 'Q') {
            return false;
        } else if (ch >= '0' && ch <= '9') {
            processNumber(inputStr);
        } else if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '=') {
            processOperator(ch);
        }
        return true;
    }
}

 

7. Main class


public class Main {

    public static void main(String[] args) {
        Calculator calculator = new Calculator();
        boolean run = true;
        while (run) {
            run = calculator.run();
        }
    }
}

 

이처럼 State Pattern은 상태에 따라 다른 로직을 수행하며 수행이 완료 되었다면 다른 상태로 바꾸는 패턴입니다. 읽어주셔서 감사합니다. 

 

전체 코드는 아래에서 확인 가능합니다:)

https://github.com/rlaehdals/design-pattern

 

GitHub - rlaehdals/design-pattern

Contribute to rlaehdals/design-pattern development by creating an account on GitHub.

github.com