Step2를 진행하기 전에 요구사항을 읽어보니
이번 단계의 핵심은 새로운 연산 기능 추가가 아니라
이라는 생각이 들었다.
Step1에서는 App 클래스의 main 메서드 안에서
입력, 연산, 출력, 반복 제어가 모두 이루어졌다.
Step2에서는
이렇게 설계하였다.
Calculator 클래스
연산 결과는 여러 개가 누적되기 때문에 List를 사용하였다.
private final List<Integer> results = new ArrayList<>();
calculate 메서드는 연산 수행, 결과 저장, 결과 반환
총 3가지 역할을 수행하도록 구현했다.
public int calculate(int num1, int num2, char operator) {
int result = 0;
switch (operator) {
case '+':
result = num1 + num2;
break;
case '-':
result = num1 - num2;
break;
case '*':
result = num1 * num2;
break;
case '/':
if (num2 == 0) {
throw new IllegalArgumentException("0으로 나눌 수 없습니다.");
}
result = num1 / num2;
break;
default:
throw new IllegalArgumentException("지원하지 않는 연산자입니다.");
}
results.add(result); // 연산 결과 저장
return result; // 결과 반환
}
Step1에서는 main 메서드에서 연산과 예외 처리를 했지만
Step2에서는 calculator가 하도록 변경했다.
잘못된 연산자나 0으로 나누는 경우에는
IllegalArgumentException을 던지고,
App 클래스에서 이를 받아 메시지를 출력하도록 했다
App 클래스에서 결과 리스트에 직접 접근하지 못하도록 했다
public List<Integer> getResults() {
return new ArrayList<>(results);
}
public void setResults(List<Integer> newResults) {
results.clear();
results.addAll(newResults);
}
외부에서 리스트를 직접 수정하는 상황을 방지할 수 있음
저장된 결과 중 가장 먼저 저장된 값을 삭제하는 기능도 추가했다.
public void removeResult() {
if (!results.isEmpty()) {
results.remove(0);
}
}
리스트가 비어 있는 상태에서 삭제를 시도하면 오류가 날 수 있기 때문에 isEmpty()로 한번 더 체크하도록 구현했다.
package com.example.calculator.step2;
import java.util.ArrayList;
import java.util.List;
public class Calculator {
//연산 결과를 저장하는 컬렉션 타입 필드 선언 및 생성
private final List<Integer> results = new ArrayList<>();
public int calculate(int num1, int num2, char operator) {
int result = 0;
switch (operator) {
case '+':
result = num1 + num2;
break;
case '-':
result = num1 - num2;
break;
case '*':
result = num1 * num2;
break;
case '/':
if (num2 == 0) {
throw new IllegalArgumentException("0으로 나눌 수 없습니다.");
}
result = num1 / num2;
break;
default:
throw new IllegalArgumentException("지원하지 않는 연산자입니다.");
}
//연산 결과를 컬렉션에 저장
results.add(result);
//return 연산 결과
return result;
}
// Getter 메서드 구현
public List<Integer> getResults() {
return new ArrayList<>(results);
}
// Setter 메서드 구현
public void setResults(List<Integer> newResults) {
results.clear();
results.addAll(newResults);
}
public void removeResult() {
// 구현
if (!results.isEmpty()) {
results.remove(0);
}
}
}
App 클래스에서는 Step1과 동일하게 구조를 유지했다.
달라진 점은 연산을 직접 수행하지 않고 Calculator 클래스의 calculate 메서드를 호출한다는 점이다.
Calculator calculator = new Calculator();
try {
int result = calculator.calculate(num1, num2, operator);
System.out.println("결과: " + result);
} catch (IllegalArgumentException e) {
System.out.println("오류: " + e.getMessage());
}
또한 getter와 removeResult 메서드를 활용해 저장된 결과를 조회하고 삭제하는 기능도 함께 확인했다.
package com.example.calculator.step2;
import java.util.Scanner;
public class App {
public static void main(String[] args) {
//Calculator 인스턴스 생성
Calculator calculator = new Calculator();
Scanner sc = new Scanner(System.in);
// 반복문 시작
while (true) {
System.out.print("첫 번째 숫자를 입력하세요:");
int num1 = sc.nextInt();
System.out.print("두 번째 숫자를 입력하세요:");
int num2 = sc.nextInt();
System.out.print("사칙연산 기호를 입력하세요: ");
char operator = sc.next().charAt(0);
try {
int result = calculator.calculate(num1, num2, operator);
System.out.println("결과: " + result);
} catch (IllegalArgumentException e) {
System.out.println("오류: " + e.getMessage());
}
// getter 활용해보기
System.out.println("저장된 결과 목록: " + calculator.getResults());
// removeResult 활용해보기
System.out.println("가장 먼저 저장된 결과를 삭제하시겠습니까? (remove 입력 시 삭제)");
String cmd = sc.next();
if (cmd.equalsIgnoreCase("remove")) {
calculator.removeResult();
System.out.println("삭제 후 결과 목록: " + calculator.getResults());
}
System.out.println("더 계산하시겠습니까? (exit 입력 시 종료)");
String answer = sc.next();
if (answer.equals("exit")) break;
}
// 반복문 종료
sc.close();
}
}

프로그램을 실행해보면 연산 결과가 리스트에 차례대로 저장되고 remove를 입력하면 가장 먼저 저장된 값이 삭제된다.
다음 Step3에서는 실수 연산, 결과 조건 조회, Enum과 스트림 등을 적용하며 계산기를 조금 더 확장해볼 예정이다.