https://toongri.tistory.com/13

https://mangkyu.tistory.com/151

다형성을 이용했을 경우

GitHub - kyukong/atdd-subway-path at step2

우아한테크코스 미션 중 지하철 경로 조회 미션에서 외부 라이브러리를 사용한 객체를 스프링 빈으로 생성하였다.

지하철 경로를 조회하는 알고리즘을 다익스트라 알고리즘을 사용하였으나 다른 라이브러리 또는 다른 알고리즘을 사용할 수 있기 때문에 사용하는 전략을 쉽게 바꾸기 위해서 다형성을 이용하였다. 변경이 쉽도록 인터페이스로 분리하였으므로 코드 내에서 해당 객체를 선언하는 것이 아닌 외부에서 입력받아오도록 스프링 빈 객체로 선언하였다.

도메인 객체

***src/main/java/wooteco/subway/domain/path/PathDecisionStrategy.java***

package wooteco.subway.domain.path;

import wooteco.subway.domain.Section;

import java.util.List;

public interface PathDecisionStrategy {

    PathDecision decidePath(final List<Section> sections, final Path path);
}

***src/main/java/wooteco/subway/domain/path/PathDijkstraDecisionStrategy.java***

package wooteco.subway.domain.path;

import org.jgrapht.GraphPath;
import org.jgrapht.alg.shortestpath.DijkstraShortestPath;
import org.jgrapht.graph.DefaultWeightedEdge;
import org.jgrapht.graph.WeightedMultigraph;
import wooteco.subway.domain.Section;

import java.util.List;

public class PathDijkstraDecisionStrategy implements PathDecisionStrategy {

    private DijkstraShortestPath<Long, DefaultWeightedEdge> dijkstraShortestPath;

    @Override
    public PathDecision decidePath(final List<Section> sections, final Path path) {
        createDijkstraGraph(sections);

        GraphPath<Long, DefaultWeightedEdge> graph = dijkstraShortestPath.getPath(path.getSource(), path.getTarget());
        return new PathDecision(graph.getVertexList(), graph.getWeight());
    }

    private void createDijkstraGraph(final List<Section> sections) {
        final WeightedMultigraph<Long, DefaultWeightedEdge> graph = new WeightedMultigraph<>(DefaultWeightedEdge.class);
        for (Section section : sections) {
            addSectionInGraph(graph, section);
        }
        dijkstraShortestPath = new DijkstraShortestPath<>(graph);
    }

    private void addSectionInGraph(final WeightedMultigraph<Long, DefaultWeightedEdge> graph, final Section section) {
        final Long upStationId = section.getUpStationId();
        final Long downStationId = section.getDownStationId();

        graph.addVertex(upStationId);
        graph.addVertex(downStationId);
        graph.setEdgeWeight(graph.addEdge(upStationId, downStationId), section.getDistance());
        graph.setEdgeWeight(graph.addEdge(downStationId, upStationId), section.getDistance());
    }
}

설정 객체

***src/main/java/wooteco/subway/config/PathConfiguration.java***

package wooteco.subway.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import wooteco.subway.domain.path.PathDecisionStrategy;
import wooteco.subway.domain.path.PathDijkstraDecisionStrategy;

@Configuration
public class PathConfiguration {

    @Bean
    public PathDecisionStrategy addPathDecisionStrategyBean() {
        return new PathDijkstraDecisionStrategy();
    }
}

설정 객체인 PathConfiguration 에서 지하철 경로를 조회하는 여러 전략 중 하나를 선택하도록 설정하였다.