다들 만연하게 전략 패턴의 이름에 대해서는 들어봤을 것입니다.
얼마전까지만 해도 Java 에 익숙하지 않던, 아니 더 나아가서 객체지향에 익숙하지 않던 저에게도 들어본 적은 있지만, 도대체 무엇인지 모르는 개념이었습니다.
이름에서부터 풍겨오는 느낌은 다양한 전략을 사용한다는 것? 이 정도로 느껴집니다.
과연 전략패턴은 무엇일까요?
전략 패턴은 알고리즘들의 패밀리를 정의하고, 각 패밀리를 별도의 클래스에 넣은 후 그들의 객체들을 상호교환할 수 있도록 하는 행동 디자인 패턴입니다.
더 쉽게 말하면, 별도의 클래스들에 알고리즘 전략들을 집어넣어놓고, 상황에 맞게 갈아끼운다는 것입니다.
근데.. 도대체 이게 왜 필요할까요?
우리가 공을 들여서 네비게이터 앱을 개발했다고 가정해볼게요.
어렵게 어렵게, 자동차로 이동할 때 출발지부터 목적지까지의 최적의 경로를 추출해내고, 안내해주게끔 만들었어요.
사람들의 반응은 뜨거웠습니다.
하지만, 점점 사람들이 도보로 이동하는 최적의 경로도 원하기 시작했어요.
서비스가 흥하기 위해서는 당연히 사용자의 피드백에 따라야겠죠?
도보로 이동하는 최적의 경로도 만들어냈습니다.
하지만, 이어서 자전거 등등 계속해서 사용자들이 원하기 시작했어요.
서비스는 흥했지만, Main 클래스의 코드는 점점 스파게티 코드가 되어갔습니다.
한 줄을 고칠 때마다, 예기치 못한 오류가 수도 없이 발생했습니다.
코드를 유지보수 하는 것이 너무 힘들어진 것입니다.
이를 어떻게 해결할 수 있을까요?
간단합니다.
하나의 클래스에 알고리즘들을 모아놓지 않으면 됩니다.
즉, 자동차, 도보, 자전거 등등의 경로를 구하는 알고리즘을 다른 클래스로 분리하면 되는 것입니다.
그러고서 상황에 맞게 알고리즘들을 선택하면 됩니다.
구조에 대한 설명을 간략하게 하면 알고리즘을 사용할 메서드를 정의해놓고, 알고리즘을 구현하는 구현체가 해당 메서드를 구현하면 되는 것입니다.
그러고서 Navigator (Context) 이를 사용하기만 하면되는 것이죠.
Navigator 는 알고리즘 내부 사정이 어떻게 되는지 신경쓰지 않아도 됩니다.
이를 통해 나온 결과를 가지고, 잘 활용하기만 하면 되는 것이죠!
public interface RouteStrategy {
경로 buildRoute(위치 A, 위치 B);
}
public class RoadStrategy implements RouteStrategy {
public 경로 buildRoute(위치 A, 위치 B) {
... 구현부
}
}
public class WakingStrategy implements RouteStrategy {
public 경로 buildRoute(위치 A, 위치 B) {
... 구현부
}
}
public class BicycleStrategy implements RouteStrategy {
public 경로 buildRoute(위치 A, 위치 B) {
... 구현부
}
}
위와 같은 형식으로 전략 부분을 설정하시면 되구요
public class Navigator {
private RouteStratgy routeStrategy;
public Navigator(RouteStratgy routeStrategy) {
this.routeStrategy = routeStrategy;
}
public 경로 buildRoute(위치 A, 위치 B) {
// 전처리
경로 route = routeStrategy.buildRoute(A, B);
// 후처리
}
}
public class Client {
public static void main(String[] args) {
Navigator 자동차경로네비게이터 = Navigator(new RoadStrategy());
Navigator 도보경로네비게이터 = Navigator(new WakingStrategy());
Navigator 자전거경로네비게이터 = Navigator(new BicycleStrategy());
...이를 사용하는 로직들
}
}
이런 식으로 사용하면 디자인 패턴을 실질적으로 활용할 수 있는 것입니다.
장점 및 단점으로 아래와 같은 점들이 있습니다.
아무래도 장점은 각 객체들에게 역할을 확실히 부여함에 따라서, 변경에 유연하다는 것인 것 같습니다.
단점으로는, 전략 패턴을 무분별하게 사용하다보면 클래스, 인터페이스로 인해서 프로그램이 커지며, 지나치게 복잡해 질 수 있다는 것입니다.
그리고, 이를 사용하는 개발자가 전략들의 차이점에 대해서 명확하게 알고 있어야 하죠!
그렇더라도, 잘 사용하면 정말 좋은 패턴인 것 같습니다!
이를 잘 활용해서 조금 더 객체지향적인 코드를 짜볼 수 있도록 노력해봅시다!
오호 이해가 아주 잘 되는군여~~!