public class Calculate {
public static double getResult(List<Double> numbers, Operator operator) {
double result = numbers.get(0);
for (int i = 1; i < numbers.size(); i++) {
result = operator.calculate(result, numbers.get(i));
}
return result;
}
}
public class OperatorHandler {
private final String input;
private char operator;
public OperatorHandler(String input) {
this.input = input;
this.operator = getOperatorChar();
OperatorValidation.validateOperator(input, operator);
}
private char getOperatorChar() {
return operator = input.charAt(input.length() - 1);
}
public Operator getOperator() {
return switch (operator) {
case '+' -> new PlusOperation();
case '-' -> new MinusOperation();
case '*' -> new MultiplyOperation();
case '/' -> new DivideOperation();
default -> throw new IllegalArgumentException(INPUT_EMPTY_OPERATOR.getMessage());
};
}
public interface Operator {
Double calculate(double a, double b);
String getOperatorSymbol();
}
기존에 해당 인터페이스를 사용하여 Plus, Minus, Multiply, Divide 클래스에 Operator 인터페이스를 상속하여 문제를 해결하였다.
나의 생각은 이랬다.
"새로운 연산자가 추가되면 클래스만 만들어주면 되니까 다형성과 SOLID 잘 준수한 거겠지?"
-> "만약 연산자 1만개 만들어야 하면 1만개 클래스 다 만들 거야? + switch문 계속 수정할 거야? OCP에 어긋나"
라는 리뷰를 받았고, 그래서 찾아본 것이 Enum으로 관리하는 것이다.
☕ 자바 Enum 열거형 타입 문법 & 응용 💯 정리
Enum 열거 타입 먼저 Enum은 "Enumeration"의 약자다. Enumeration은 "열거, 목록, 일람표" 라는 뜻을 가지고 있으며, 보통 한글로는 열거형이라고 부른다. 즉, 열거형(enum)은 요소, 멤버라 불리는 명명된 값
inpa.tistory.com
위 블로그를 통해 고친 코드가 아래 코드이다.
package operator;
import java.util.function.DoubleBinaryOperator;
import static exception.ErrorMessage.CANNOT_DIVIDE_BY_ZERO;
import static exception.ErrorMessage.INPUT_EMPTY_OPERATOR;
public enum Operation {
PLUS("+", (x, y) -> x + y),
MINUS("-", (x, y) -> x - y),
MULTIPLY("*", (x, y) -> x * y),
DIVIDE("/", (x, y) -> {
if (y == 0) {
throw new IllegalArgumentException(CANNOT_DIVIDE_BY_ZERO.getMessage());
}
return x / y;
});
private final DoubleBinaryOperator op;
private final String symbol;
Operation(String symbol, DoubleBinaryOperator op) {
this.symbol = symbol;
this.op = op;
}
public String getSymbol(){
return symbol;
}
public double calculate(double x, double y) {
return op.applyAsDouble(x, y);
}
public static Operation fromSymbol(char symbol) {
for (Operation op : Operation.values()) {
if (op.symbol.equals(String.valueOf(symbol))) {
return op;
}
}
throw new IllegalArgumentException(INPUT_EMPTY_OPERATOR.getMessage());
}
}
해당 코드에서 fromSymbol() 메서드를 실행하면 Operation.values()에 의해 열거형을 순회한다.
또한, DoubleBinaryOperator는 Java에서 제공하는 함수형 인터페이스이다. double 타입 인수 2개를 받아 double을 리턴한다.
public class Calculate {
public static double getResult(List<Double> numbers, Operator operator) {
double result = numbers.get(0);
for (int i = 1; i < numbers.size(); i++) {
result = operator.calculate(result, numbers.get(i));
}
return result;
}
}
클래스의 이름을 동사로 지었었는데, 명사 Calculator로 변경하였고, getResult메서드 명을 calculate로 변경하였다.
그리고 정적 메서드만 있는 클래스에는 private로 생성자를 만들었다.
Validation을 Input과 operator로 분리했었는데, 어차피 입력 받은 문자를 검증하는 것이기 때문에 InputValidation으로 통합시켰다.
또한, for문을 stream 식으로 변경하였다.
stringCalculatePOJO(1) - IntelliJ에서 Test 디렉토리 생성 (1) | 2025.02.14 |
---|---|
AddStringPOJO(6) - Test 코드 작성 (0) | 2025.02.04 |
AddStringPOJO(5) - [Refactor] 메서드 책임 분할 (0) | 2025.02.03 |
addStringPOJO(4) - 정적 메서드로 변경 (0) | 2025.01.09 |
addStringPOJO(3) - 예외 처리 방식 변경 (0) | 2025.01.05 |