디자인 패턴 중 하나인 전략 패턴에 대해서 알아보겠습니다. 회사에서 리팩토링도 하고 새로운 서비스를 개발하기 위해서 알아보던 중에 전략 패턴이 적절한 것 같아서 조사하게 되었습니다.
전략 패턴 ( Strategy Pattern )
객체들이 할 수 있는 행위를 클래스로 정의하고, 유사한 행위들은 캡슐화하는 인터페이스를 정의합니다. 객체의 행위를 바꾸고 싶은 경우에는 직접 행위를 수정하지 않고 전략을 바꿔주어 유연한 확장이 가능하도록 설계하는 것을 말합니다.
전략 패턴 사용하는 이유
사용하는 이유를 알기 위해서 문제점을 발견해 보겠습니다. Season이라는 인터페이스가 있고 이를 구현한 Summer와 Winter 클래스가 있습니다. 그리고 Summer와 Winter를 사용하는 Person도 있습니다.
위 구조를 코드로 바꿔주면 아래와 같습니다.
pulic interface Season {
public void plan();
}
public class Summer implements Season {
public void plan(){
System.out.println("바다로 여행을 가자!");
}
}
public class Winter implements Season {
public void plan(){
System.out.println("스키장으로 여행을 가자!");
}
}
public class Person {
public static void main (String args[]){
Season summer = new Summer();
Season winter = new Winter();
summer.plan();
winter.plan();
}
}
여름에는 바다를 가야하고, 겨울에는 스키장을 가야 제대로 놀 수 있습니다. 그러던 어느날 여름에 계곡으로 가는 것이 유행이 되었다고 합니다. 그래서 여름에 계곡으로 가는 것으로 아래와 같이 바꾸었습니다.
public class Summer implements Season {
public void plan(){
System.out.println("계곡으로 여행을 가자!");
}
}
저의 경우 이렇게 많이 설계했었습니다. 그런데 이러한 방식은 확장성이 낮습니다. 만약에 고객이 새로운 요구를 추가한다면 메서드를 계속 수정해야 하기 때문입니다. 이는 SOLID의 원칙 중 OCP (Open-Closed Principle)에 위배 됩니다. 즉, 메서드는 수정되지 않은 채로 행위가 수정되어야 합니다. 그렇다면, 어떻게 메서드를 수정하지 않고 행위를 수정할 수 있을까요? 이제 전략 패턴이 힘을 써볼 때입니다.
전략 패턴 구현
코드가 유연성을 가지도록 설계해보겠습니다.
첫 번째로, 먼저 전략을 만들어야 합니다. 예시에서의 나타난 전략은 '바다로 여행'가는 것과 '스키장으로 여행'가는 것이 있습니다. 여행 기반인 Strategy 클래스를 생성하겠습니다. 그리고 두 클래스는 plan() 메서드를 구현해서 어디로 여행을 갈 것인지 구현합니다.
그리고 두 가지 전략을 캡슐화 하기 위한 TripStrategy 인터페이스를 생성합니다. 이렇게 캡슐화하는 이유는 다른 전략(강남, 산, 제주도, 해외 등)이 추가될 것을 고려한 설계입니다.
위 구조를 코드로 바꿔주면 아래와 같습니다.
public interface TripStrategy {
public void plan();
}
public class BeachStrategy implements TripStrategy {
public void plan(){
System.out.println("바다로 여행을 가자!");
}
}
public class SkiResortStrategy implements TripStrategy {
public void plan(){
System.out.println("스키장으로 여행을 가자!");
}
}
두 번째로, 행위를 사용할 계절에 대한 클래스를 정의해야 합니다. 여름과 겨울에는 각자의 계획을 plan()으로 보여주고 있습니다. 각 계절 클래스에서는 여행 계획을 plan() 메서드로 직접 구현하지 않고, 어떻게 계획할 건지에 대한 전략을 설정하고, 그 설정된 전략 방식을 사용할 것입니다. 그래서 전략을 설정할 setTripStrategy()를 만들겠습니다.
위 구조를 코드로 바꿔주면 아래와 같습니다.
public class Season {
private TripStrategy tripStrategy;
public void plan(){
tripStrategy.plan();
}
public void setTripStrategy(TripStrategy tripStrategy){
this.tripStrategy = tripStrategy;
}
}
public class Summer extends Season{
}
public class Winter extends Season{
}
세 번째로, 놀러갈 사람( Person )을 구현하겠습니다.
Summer와 Winter 객체를 생성한 후에 어디로 여행을 갈지를 setTripStrategy()로 설정해줍니다.
만약에 여름에 스키리조트를 가고 싶을 수도 있습니다. 그럴 경우에 setTripStrategy()로 여행지를 설정할 수 있습니다.
이렇게 보면 프로그램 개발이 굉장히 유연하게 되었다는 것을 볼 수 있습니다.
public class Person {
public static void main(String args[]){
Season summer = new Summer();
Season winter = new Winter();
summer.setTripStrategy(new BeachStrategy());
winter.setTripStrategy(new SkiResortStrategy());
summer.plan();
winter.plan();
summer.setTripStrategy(new SkiResortStrategy());
summer.plan();
}
}
참고
- https://victorydntmd.tistory.com/292
끝.
'IT > Others' 카테고리의 다른 글
객체 지향 상속의 종류 : Subclassing 과 Subtyping (0) | 2022.11.26 |
---|---|
싱글톤 패턴 (0) | 2022.08.27 |
DMA (Direct Memory Access) (0) | 2022.05.11 |
DBeaver 설치 및 MariaDB와 연동 (0) | 2022.03.13 |
MariaDB 설치 (0) | 2022.03.12 |