[우아한테크코스 3기] 3주차 프리코스 java-subway-map-precourse
3기 3주차 프리코스 문제를 풀어 보았습니다.
최종 코딩 테스트 대비가 목적이기 때문에 최대한 빠른시간에 동작하도록 구현하는 것이 목표였습니다.
위와 같은 설계로 코드를 작성하였습니다.
1. 핵심
Line, Station, LineRepository, StationRepository를 미리 제공을 하고 있으며, 4개의 클래스를 어떻게 사용할지 빠르게 파악하는 것이 핵심입니다.
4개의 클래스를 먼저 살펴보도록 하겠습니다.
Line.java
package subway.domain;
public class Line {
private String name;
public Line(String name) {
this.name = name;
}
public String getName() {
return name;
}
// 추가 기능 구현
}
Station.java
package subway.domain;
public class Station {
private String name;
public Station(String name) {
this.name = name;
}
public String getName() {
return name;
}
// 추가 기능 구현
}
LineRepository.java
package subway.domain;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
public class LineRepository {
private static final List<Line> lines = new ArrayList<>();
public static List<Line> lines() {
return Collections.unmodifiableList(lines);
}
public static void addLine(Line line) {
lines.add(line);
}
public static boolean deleteLineByName(String name) {
return lines.removeIf(line -> Objects.equals(line.getName(), name));
}
}
StationRepository.java
package subway.domain;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
public class StationRepository {
private static final List<Station> stations = new ArrayList<>();
public static List<Station> stations() {
return Collections.unmodifiableList(stations);
}
public static void addStation(Station station) {
stations.add(station);
}
public static boolean deleteStation(String name) {
return stations.removeIf(station -> Objects.equals(station.getName(), name));
}
}
저는 Station과 Line을 각각 역에 대한 객체와 노선에 대한 객체로 파악을 하였으며
StationRepository와 LineRepository를 각각 역에 대한 저장소, 노선에 대한 저장소 역할로 파악을 하였습니다.
추가한 점이 있다면 Line 객체에는 노선에 대한 이름만 (2호선, 3호선) 인스턴스 변수로 받아들이고 있는데, 여기에 노선에 속하는 station 정보까지 저장할 수 있는 list를 추가해 주었습니다.
그리고 노선에 대한 정보를 출력할 수 있는 toString 메서드와 toAllString 메서드를 생성하였습니다.
이 메서드를 OutputView 에서 사용하도록 하였습니다.
package subway.domain;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class Line {
private String name;
private List<Station> stations = new ArrayList<>();
public Line(String name) {
this.name = name;
}
public String getName() {
return name;
}
// 추가 기능 구현
public void addStation(String station) {
stations.add(new Station(station));
}
@Override
public String toString() {
return name;
}
public void addStationByOrder(String stationName, Integer order) {
stations.add(order, new Station(stationName));
}
public boolean deleteStationByName(String targetStation) {
return stations.removeIf(station -> Objects.equals(station.getName(), targetStation));
}
public String toAllString() {
String stationInfo = "";
stationInfo += String.format("[INFO] %s%n", name);
stationInfo += String.format("[INFO] ---%n");
for (Station station : stations) {
stationInfo += String.format("[INFO] %s%n", station.toString());
}
stationInfo += String.format("%n");
return stationInfo;
}
}
2. 구현 방법
Application.java
Application에서 첫 main 화면 선택권을 받고 각각의 controller에서 동작을 구현하는 방식으로 진행을 하였습니다.
## 메인 화면
1. 역 관리
2. 노선 관리
3. 구간 관리
4. 지하철 노선도 출력
Q. 종료
1번 2번 3번을 각각 선택하게 되면 StationController, LineController, SectionController로 이동을 하게 됩니다.
package subway;
import java.util.Scanner;
import subway.controller.LineController;
import subway.controller.SectionController;
import subway.controller.StationController;
import subway.domain.Line;
import subway.domain.LineRepository;
import subway.domain.Station;
import subway.domain.StationRepository;
import subway.view.InputView;
import subway.view.OutputView;
public class Application {
public static void main(String[] args) {
final Scanner scanner = new Scanner(System.in);
StationController stationController = new StationController(scanner);
LineController lineController = new LineController(scanner);
SectionController sectionController = new SectionController(scanner);
initStation();
initLine();
while (true) {
String mainSelect = InputView.requireMain(scanner);
if (mainSelect.equals("1")) {
stationController.run();
}
if (mainSelect.equals("2"))
lineController.run();
if (mainSelect.equals("3"))
sectionController.run();
if (mainSelect.equals("4")) {
LineRepository lineRepository = new LineRepository();
OutputView.printAllLineState(lineRepository);
}
if (mainSelect.equals("Q")) {
break;
}
}
}
private static void initLine() {
//- 2호선: 교대역 - 강남역 - 역삼역
//- 3호선: 교대역 - 남부터미널역 - 양재역 - 매봉역
//- 신분당선: 강남역 - 양재역 - 양재시민의숲역
Line line = new Line("2호선");
line.addStation("교대역");
line.addStation("강남역");
line.addStation("역삼역");
LineRepository.addLine(line);
line = new Line("3호선");
line.addStation("교대역");
line.addStation("남부터미널역");
line.addStation("양재역");
line.addStation("매봉역");
LineRepository.addLine(line);
line = new Line("신분당선");
line.addStation("강남역");
line.addStation("양재역");
line.addStation("양재시민의숲역");
LineRepository.addLine(line);
}
private static void initStation() {
StationRepository.addStation(new Station("교대역"));
StationRepository.addStation(new Station("강남역"));
StationRepository.addStation(new Station("역삼역"));
StationRepository.addStation(new Station("남부터미널역"));
StationRepository.addStation(new Station("양재역"));
StationRepository.addStation(new Station("양재시민의숲역"));
StationRepository.addStation(new Station("매봉역"));
}
}
StationController.java
## 역 관리 화면
1. 역 등록
2. 역 삭제
3. 역 조회
B. 돌아가기
역 등록 및 삭제, 조회에 대한 기능을 구현하였습니다.
Controller이기 때문에 view와 domain을 연결해 주는 기능을 맡고 있으며 역 등록 및 삭제, 조회 기능은 StationRepository에게 메세지를 보내서 기능을 구현하도록 진행하였습니다.
package subway.controller;
import java.util.Scanner;
import subway.domain.Station;
import subway.domain.StationRepository;
import subway.view.InputView;
import subway.view.OutputView;
public class StationController {
private final Scanner scanner;
public StationController(Scanner scanner) {
this.scanner = scanner;
}
public void run() {
String main = InputView.stationMain(scanner);
// ## 역 관리 화면
// 1. 역 등록
// 2. 역 삭제
// 3. 역 조회
// B. 돌아가기
if (main.equals("1")) {
String station = InputView.registStation(scanner);
StationRepository.addStation(new Station(station));
InputView.finishRegistStation();
}
if (main.equals("2")) {
String deleteStation = InputView.deleteStation(scanner);
StationRepository.deleteStation(deleteStation);
OutputView.finishDeleteStation();
}
if (main.equals("3")) {
StationRepository stationRepository = new StationRepository();
OutputView.printStationState(stationRepository);
}
}
}
StationRepository.java
package subway.domain;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
public class StationRepository {
private static final List<Station> stations = new ArrayList<>();
public static List<Station> stations() {
return Collections.unmodifiableList(stations);
}
public static void addStation(Station station) {
stations.add(station);
}
public static boolean deleteStation(String name) {
return stations.removeIf(station -> Objects.equals(station.getName(), name));
}
@Override
public String toString() {
String stationInfo = "";
for (Station station : stations) {
stationInfo += String.format("[INFO] %s%n", station.toString());
}
return stationInfo;
}
}
역 등록, 삭제, 조회 기능을 각각 addStation, deleteStation, toString 메서드를 이용하여 구현을 하였습니다.
나머지 노선 관리 및 구역 관리는 역 관리와 동일한 방법으로 진행을 하였기 때문에 설명을 줄이도록 하겠습니다.
3. 익숙해져야 하는 부분
removeIf
특정 조건을 만족 할 때 제거한다.
removeIf 메서드를 기억하고 있는다면 한층 더 깔끔하게 코드를 구현할 수 있다는 걸 기억하면 좋을 것 같습니다.
public static boolean deleteStation(String name) {
return stations.removeIf(station -> Objects.equals(station.getName(), name));
}
unmodifiableList
unmodifiableList() 메소드에서 리턴되는 리스트 레퍼런스는 'Read-Only' 용도로만 사용할 수 있으며, 수정하려는 메소드(가령 set(), add(), addAll() 등)를 호출하면 UnsupportedOperationException 이 발생한다는 것이다.
public static List<Station> stations() {
return Collections.unmodifiableList(stations);
}
add (index)
특정 index에 값을 넣을 수 있도록 해주는 기능이다.
public void addStationByOrder(String stationName, Integer order) {
stations.add(order, new Station(stationName));
}
위 3가지 기능을 알고 있으면 이 프로젝트를 구현하는데 있어서 크게 어려움은 없었을 것이라고 생각합니다.