racing 콘솔 프로그램 구현 바로 시작했습니다 ㅎㅎ
먼저 어떤 프로그램을 구현해야 하는지 설명해드릴게요.
위에 보이는 사진은 기능 요구사항과, 실행 결과 입니다. 자동차를 입력 받고, 5번 움직였을 경우의 결과를 도출하는 프로그램을 구현해야 합니다.
기능구현목록
프로그램을 구현하기 전에 기능 구현 목록을 정리해봤습니다! 어떤 생각을 가지고 저런 식으로 작성하였는지 설명하겠습니다.
Car :
moveCount(움직인 횟수)를 필드로 두어 일급컬렉션을 적용합니다.
랜덤 숫자를 생성하는 인터페이스를 이용하여 움직일지 말지 정하는 로직을 구현할 생각입니다.
Cars :
List<Car> 를 필드로 두어 일급컬렉션을 적용합니다.
전체적인 Car를 관리합니다.
CarNameParser :
자동차 이름을 한 번에 입력 받을 때, 이름을 나눠줄 수 있도록 관리하는 클래스입니다.
String carName 대신 Name 으로 원시값 포장하여 관리할 생각입니다.
List 을 필드로 두어 일급컬렉션을 적용합니다.
* CreateRandomNumber
public interface CreateRandomNumber {
int generateRandomNumber();
}
랜덤 숫자를 생성하는 인터페이스입니다.
* CarRandomNumber
public class CarRandomNumber implements CreateRandomNumber {
private static final Random randomNumberGenerator = new Random();
private static final int LAST_NUMBER = 10;
@Override
public int generateRandomNumber() {
return randomNumberGenerator.nextInt(LAST_NUMBER);
}
}
위에 인터페이스를 상속받아, 자동차를 움직일 수 있는 숫자를 생성하는 클래스를 구현하였습니다.
*Name
public static Name from(final String name) {
validateNameRange(name);
return new Name(name);
}
Name 클래스입니다. 정적 팩토리 메서드를 사용하여 검증을 할 수 있게 구현하였습니다.
* Car
private final Name carName;
public int moveCount;
public Car(int moveCount, String carName) {
this.moveCount = moveCount;
this.carName = Name.from(carName);
}
carName 을 입력받아 Name 으로 감싸주었고, moveCount 를 주입받도록 하였습니다.
Cars 에서 자동차 한 번에 생성시, moveCount 를 0으로 주입해 줄 생각입니다. (이 부분은 작성하고 나니 약간 후회가 되네요 ㅠ 그냥 처음부터 0으로 초기화 해줄걸..)
public void moveCar(CreateRandomNumber createRandomNumber) {
if (createRandomNumber.generateRandomNumber() >= CAR_MOVE_BOUNDARY) {
moveCount++;
}
}
그리고 위에서 만들었던 인터페이스를 통해 moveCount 를 증가시켜주는 로직을 구현하였습니다.
* CarNameParser
public final List<Name> carNames;
public CarNameParser(String carNames) {
this.carNames = parseCarName(carNames);
}
List<Name>을 필드로 두어 관리할 수 있도록 구현하였습니다.
private List<Name> parseCarName(String carNames) {
String[] parsedCarNames = carNames.split(SPLIT_STRING_DELIMITER);
List<Name> Names = new ArrayList<>();
for (String carName : parsedCarNames) {
Names.add(Name.from(carName));
}
return Names;
}
들어온 자동차 이름들을 나눠주는 로직입니다. Name 으로 감싸주도록 하였습니다.
* Cars
private final List<Car> cars;
public Cars(List<Name> carNames) {
this.cars = makeCars(carNames);
}
List<Car> 를 필드로 두어 일급컬렉션을 적용하였습니다.
private List<Car> makeCars(List<Name> carNames) {
List<Car> cars = new ArrayList<>();
for (Name carName : carNames) {
Car car = new Car(INITIAL_NUMBER, carName.getName());
cars.add(car);
}
return cars;
}
위와 같은 방식으로 자동차 묶음들을 생성해 주었습니다.
public List<String> getWinner() {
return cars.stream()
.filter(this::isMaxCount)
.map(Car::getCarName)
.collect(Collectors.toList());
}
private boolean isMaxCount(Car car) {
return car.getMoveCount() == getMaxCount();
}
private int getMaxCount() {
return cars.stream()
.mapToInt(Car::getMoveCount)
.max()
.orElse(INITIAL_NUMBER);
}
그리고 해당 클래스는 Cars 들을 한꺼번에 관리하고 있다보니, 가장 높은 moveCount 를 가지는 자동차를 뽑는 우승자 로직에 책임이 있다고 생각하였습니다.
따라서 위의 코드처럼 우승자 메서드도 Cars 클래스에서 구현하였습니다.
* 결과
위의 클래스들을 컨트롤러에서 잘 조립하니, 결과가 올바르게 나왔습니다!
'스프링 > 미션' 카테고리의 다른 글
[Spring] racing - 후기 (1) | 2024.10.01 |
---|---|
[Spring] racing - API 서버 구현(2) (0) | 2024.09.30 |
[Spring] racing - API 서버 구현(1) (0) | 2024.09.30 |
[Spring] racing 콘솔 테스트 코드 작성 - 인터페이스는 어떻게 테스트 해야할까? (1) | 2024.09.30 |
[Spring] 미션 시작! (1) | 2024.09.30 |