Skip to content

Commit 6b9381e

Browse files
authored
Step1 (#2998)
* docs: <1단계> 기능 요구 사항 정리 * docs: <1단계> 정수에 대한 사칙연산 기능 구현 * docs: <1단계> 수식에서 숫자, 연산자 분류 기능 구현 * docs: <1단계> Numbers 일급 콜렉션 * docs: <1단계> Operations 일급 콜렉션 * docs: <1단계> 둘 이상의 연산자 연산 * docs: <1단계> 사용자로부터 문자열 입력 * feat: <1단계> 피드백 반영 - 축약어 제거 - 상수와 변수 사이 공백 추가 * feat: <1단계> 피드백 반영 - 팩토리 패턴 도입 - stream 활용 * feat: <1단계> 피드백 반영 - Operator Enum 활용 * feat: <1단계> 피드백 반영 - Operator.calculate 메서드 시그니처 변경 - stream 활용 * feat: <1단계> 피드백 반영 - 메소드 네임 변경 * feat: <1단계> 피드백 반영 - StringCalculator 클래스 기능 분리
1 parent 471f91b commit 6b9381e

17 files changed

+474
-1
lines changed

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,14 @@
66
* 모든 피드백을 완료하면 다음 단계를 도전하고 앞의 과정을 반복한다.
77

88
## 온라인 코드 리뷰 과정
9-
* [텍스트와 이미지로 살펴보는 온라인 코드 리뷰 과정](https://github.com/next-step/nextstep-docs/tree/master/codereview)
9+
* [텍스트와 이미지로 살펴보는 온라인 코드 리뷰 과정](https://github.com/next-step/nextstep-docs/tree/master/codereview)
10+
11+
## 기능 요구 사항
12+
- [x] 문자열로부터 공백으로 구분된 숫자와 연산자를 분류한다.
13+
- [x] 덧셈 연산을 계산한다.
14+
- [x] 뺄셈 연산을 계산한다.
15+
- [x] 곱셈 연산을 계산한다.
16+
- [x] 나눗셈 연산을 계신한다. (단, 정수로 떨어지는 경우로 한정한다.)
17+
- [x] 둘 이상의 연산자가 존재할 경우, 앞에서부터 차례로 계산한다.
18+
- [x] 숫자, 연산자에 대한 예외 처리를 한다.
19+
- [x] 사용자로부터 문자열을 입력받는다.

src/main/java/.gitkeep

Whitespace-only changes.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package domain;
2+
3+
import view.InputView;
4+
5+
public class CalculatorMain {
6+
public static void main(String[] args) {
7+
8+
StringCalculator stringCalculator = new StringCalculator();
9+
10+
String expression = InputView.readExpression();
11+
validExpression(expression);
12+
13+
System.out.println(">>> " + stringCalculator.calculate(readNumbers(expression), readOperators(expression)));
14+
}
15+
16+
static void validExpression(String expression) {
17+
if (expression == null || expression.isBlank()) {
18+
throw new IllegalArgumentException("유효한 표현식이 아닙니다.");
19+
}
20+
}
21+
22+
static Operations readOperators(String expression) {
23+
OperatorFactory operatorFactory = new OperatorFactory();
24+
return new Operations(operatorFactory.extractList(splitByBlank(expression)));
25+
}
26+
27+
static Numbers readNumbers(String expression) {
28+
CalculatorTokenFactory numbersFactory = new NumbersFactory();
29+
return new Numbers(numbersFactory.extractList(splitByBlank(expression)));
30+
}
31+
32+
private static String[] splitByBlank(String expression) {
33+
return expression.split(" ");
34+
}
35+
36+
37+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package domain;
2+
3+
import java.util.List;
4+
5+
public interface CalculatorTokenFactory {
6+
<T> List<T> extractList(String[] splits);
7+
}

src/main/java/domain/Numbers.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package domain;
2+
3+
import java.util.ArrayList;
4+
import java.util.Deque;
5+
import java.util.LinkedList;
6+
import java.util.List;
7+
8+
public class Numbers {
9+
10+
private Deque<Integer> numbers;
11+
12+
public Numbers(List<Integer> numbers) {
13+
this.numbers = new LinkedList<>(numbers);
14+
}
15+
16+
public Integer getNextNumber() {
17+
return numbers.pollFirst();
18+
}
19+
20+
public List<Integer> getNumbers() {
21+
return new ArrayList<>(numbers);
22+
}
23+
24+
public void add(int element) {
25+
numbers.addFirst(element);
26+
}
27+
28+
public int size() {
29+
return numbers.size();
30+
}
31+
32+
public boolean isContain(Integer number) {
33+
return numbers.contains(number);
34+
}
35+
36+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package domain;
2+
3+
import java.util.List;
4+
import java.util.stream.Collectors;
5+
import java.util.stream.IntStream;
6+
7+
public class NumbersFactory implements CalculatorTokenFactory {
8+
9+
@Override
10+
public List<Integer> extractList(String[] splits) {
11+
return IntStream.range(0, splits.length)
12+
.filter(i -> isNumberPosition(i))
13+
.mapToObj(i -> Integer.parseInt(splits[i]))
14+
.collect(Collectors.toList());
15+
}
16+
17+
private boolean isNumberPosition(int index) {
18+
return index % 2 == 0;
19+
}
20+
21+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package domain;
2+
3+
import java.util.Deque;
4+
import java.util.LinkedList;
5+
import java.util.List;
6+
7+
public class Operations {
8+
9+
private Deque<Operator> operators;
10+
11+
public Operations(List<Operator> operators) {
12+
this.operators = new LinkedList<>(operators);
13+
}
14+
15+
public boolean hasNext() {
16+
return !operators.isEmpty();
17+
}
18+
19+
public Operator next() {
20+
if (operators.isEmpty()) {
21+
return null;
22+
}
23+
return operators.pollFirst();
24+
}
25+
26+
public boolean isContain(Operator operator) {
27+
return operators.contains(operator);
28+
}
29+
30+
}

src/main/java/domain/Operator.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package domain;
2+
3+
import java.security.InvalidParameterException;
4+
import java.util.Arrays;
5+
import java.util.function.BiFunction;
6+
7+
public enum Operator {
8+
PLUS("+", (left, right) -> left + right),
9+
SUBTRACT("-", (left, right) -> left - right),
10+
MULTIPLY("*", (left, right) -> left * right),
11+
DIVIDE("/", (left, right) -> left / right);
12+
13+
private String symbol;
14+
private BiFunction<Integer, Integer, Integer> biFunction;
15+
16+
Operator(String symbol, BiFunction<Integer, Integer, Integer> biFunction) {
17+
this.symbol = symbol;
18+
this.biFunction = biFunction;
19+
}
20+
21+
public Integer calculate(int left, int right) {
22+
if (this == DIVIDE && right == 0) {
23+
throw new InvalidParameterException("0으로 나눌 수 없습니다.");
24+
}
25+
return biFunction.apply(left, right);
26+
}
27+
28+
public static Operator toOperation(String symbol) {
29+
return Arrays.stream(values())
30+
.filter(operator -> operator.symbol.equals(symbol))
31+
.findAny()
32+
.orElseThrow(() -> new InvalidParameterException("유효한 연산자가 아닙니다."));
33+
}
34+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package domain;
2+
3+
import java.util.List;
4+
import java.util.stream.Collectors;
5+
import java.util.stream.IntStream;
6+
7+
public class OperatorFactory implements CalculatorTokenFactory {
8+
9+
@Override
10+
public List<Operator> extractList(String[] splits) {
11+
return IntStream.range(0, splits.length)
12+
.filter(i -> isOperatorPosition(i))
13+
.mapToObj(i -> Operator.toOperation(splits[i]))
14+
.collect(Collectors.toList());
15+
}
16+
17+
private boolean isOperatorPosition(int index) {
18+
return index % 2 != 0;
19+
}
20+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package domain;
2+
3+
public class StringCalculator {
4+
5+
public int calculate(Numbers numbers, Operations operations) {
6+
int result = 0;
7+
while (operations.hasNext()) {
8+
Operator operator = operations.next();
9+
Integer left = numbers.getNextNumber();
10+
Integer right = numbers.getNextNumber();
11+
result = operator.calculate(left, right);
12+
13+
numbers.add(result);
14+
}
15+
return result;
16+
}
17+
}
18+

0 commit comments

Comments
 (0)