[디자인패턴] 전략 패턴(Strategy Pattern)
💡 코드가 보이지 않으시다면 드래그 혹은 오른쪽 아래 🌜 아이콘을 눌러 테마 색을 변경해주세요.
안녕하세요!
키크니 개발자 입니다. 🦒
전략 패턴이란?
- 옵션들마다의 행동들을 모듈화해서 독립적이고 상호 교체 가능하게 만드는 것입니다.
- 객체들이 할 수 있는 동작을 각각의 전략으로 만들어 놓고 동적으로 동작을 변경해야 한다면 전략만 변경하여 동작이 바뀌도록 하는 패턴입니다.
- 일반적으로 if else로 구성된 코드 블록이 비슷한 기능 혹은 비슷한 알고리즘을 수행하는 경우에 전략 패턴을 적용함으로써 코드를 확장시킬 수 있습니다.
전략 패턴의 장점은?
- Strategy는 파싱 클래싱의 좋은 대안입니다. 클래스를 상속하고 메소드를 오버라이딩 하는 대신 단순한 인터페이스를 구현만 하면 됩니다.
- Strategy 객체는 Context 클래스를 필요로 하지 않으며 알고리즘 특정 데이터에 집중할 수 있습니다.
- 시스템에 새로운 Strategy를 추가하기 쉽습니다.
전략 패턴의 단점은?
- 통신 오버헤드가 클 수 있습니다. 즉, Strategy 객체의 전달된 인자의 일부가 사용되지 않을 수 있습니다.
예시
'얄팍한 코딩사전 : 객체지향 디자인패턴 1' 을 참고했습니다.
상황
위와 같이 탭으로 구별되는 검색기능이 있다고 가정합니다.
분홍색으로 표시 된 버튼들 중 하나를 눌러서 모드를 설정하고,
선택 된 모드에 따라서 검색 버튼을 눌렀을 때 실행되는 검색의 방식이 결정되도록 하는 상황입니다.
즉 프로그램 실행 중 모드가 바뀔 때마다 검색이 이뤄지는 방식으로 전략이 수정된다고 볼 수 있습니다.
Before
전략 패턴을 활용하지 않는 코드 입니다.
public class MyProgram {
private SearchButton searchButton = new SearchButton(this);
public Mode mode = Mode.ALL; // (1)
public void setModeAll() { mode = Mode.ALL; }
public void setModeImage() { mode = Mode.IMAGE; }
public void setModeNews() { mode = Mode.NEWS; }
public void setModeMap() { mode = Mode.MAP; }
}
(1) 우선 현재 어떤 모드가 선택되어있는지 변수를 하나 만들어서 값을 넣어둡니다.
- 버튼들이 각각 메소드들(setModeAll(), setModeImage(), setModeNews(), setModeMap())을 실행한다고 가정합니다.
public enum Mode {
ALL, IMAGE, NEWS, MAP
}
public class SearchButton {
MyProgram myProgram;
public SearchButton(MyProgram myProgram) {
myProgram = myProgram;
}
public void onClick() { // (1)
if (myProgram.mode == Mode.ALL) {
System.out.println("SEARCH ALL");
// 전체 검색하는 코드
// ...
} else if (myProgram.mode == Mode.IMAGE) {
System.out.println("SEARCH IMAGE");
// 이미지 검색하는 코드
// ...
} else if (myProgram.mode == Mode.NEWS) {
System.out.println("SEARCH NEWS");
// 뉴스 검색하는 코드
// ...
} else if (myProgram.mode == Mode.MAP) {
System.out.println("SEARCH MAP");
// 지도 검색하는 코드
// ...
}
}
}
(1) searchButton에 onClick()이 실행되면 if문으로 그에 해당하는 동작이 행해집니다.
- 각각의 수정사항이 생기거나 기능이 추가되면 searchButton의 onClick 메소드를 그때그때 다시 수정해줘야합니다.
이렇게 구현을 하게 된다면 소프트웨어가 커지고 복잡해질수록 코드를 분석하고 관리하기 어려워집니다.
전략패턴은 모드마다의 동작 하나하나를 모듈로 따로 분리해서,
이 버튼들을 누를때마다 검색버튼을 누를때 실행될 검색 모듈을 갈아끼워주는 방식으로 코드를 구현합니다.
After
public class Main {
public static void main(String[] args) {
MyProgram myProgram = new MyProgram();
myProgram.testProgram();
}
}
public class SearchButton {
MyProgram myProgram;
public SearchButton(MyProgram myProgram) {
myProgram = myProgram;
}
private SearchStrategy searchStrategy = new SearchStrategyAll(); // 1
public void setSearchStrategy(SearchStrategy searchStrategy) { // 2
searchStrategy = searchStrategy;
}
public void onClick() {
searchStrategy.search();
}
}
- 기존 onClick() 메소드에 if else문으로 탭 버튼에 맞춰 기능을 실행했지만, 전략 패턴을 사용한 후에는 SearchStrategy interface를 implements한 class의 search()로 기능을 실행합니다.
- 1 ) searchStrategy는 처음에 SearchStrategyAll 구현체로 초기화 되어있지만, 2)에 있는 setter를 통해서 SearchStrategy 인터페이스를 입은 다른 구현클래스(검색 전략)로 갈아끼울 수 있습니다.
public interface SearchStrategy {
public void search();
}
class SearchStrategyAll implements SearchStrategy {
@Override
public void search() {
System.out.println("SEARCH ALL");
// 전체 검색하는 코드
}
}
class SearchStrategyImage implements SearchStrategy {
@Override
public void search() {
System.out.println("SEARCH IAMGE");
// 이미지 검색하는 코드
}
}
class SearchStrategyNews implements SearchStrategy {
@Override
public void search() {
System.out.println("SEARCH NEWS");
// 뉴스 검색하는 코드
}
}
class SearchStrategyMap implements SearchStrategy {
@Override
public void search() {
System.out.println("SEARCH MAP");
// 지도 검색하는 코드
}
}
- 각각 SearchStrategy를 implements 한 class는 onClick() 안에 있는 searchStrategy.search()를 실행시킬 수 있습니다.
- 수정사항이 있으면 해당 클래스를 찾아 내용을 수정하면 되고,
새 검색 방식이 추가가 되면 SearchStrategy를 implements한 새 클래스를 만들어서 연결해주면됩니다.
public class MyProgram {
private SearchButton searchButton = new SearchButton(this);
public Mode mode = Mode.ALL;
public void setModeAll() {
searchButton.setSearchStrategy(new SearchStrategyAll());
}
public void setModeImage() {
searchButton.setSearchStrategy(new SearchStrategyImage());
}
public void setModeNews() {
searchButton.setSearchStrategy(new SearchStrategyNews());
}
public void setModeMap() {
searchButton.setSearchStrategy(new SearchStrategyMap());
}
public void testProgram() {
searchButton.onClick(); // "SEARCH ALL" 출력
setModeImage(); // 이미지검색 모드로 변경
searchButton.onClick(); // "SEARCH IMAGE" 출력
setModeNews(); // 뉴스검색 모드로 변경
searchButton.onClick(); // "SEARCH NEWS" 출력
setModeMap(); // 지도검색 모드로 변경
searchButton.onClick(); // "SEARCH MAP" 출력
}
}
위의 예시를 본 후 아래의 예시를 보니 전략 패턴에 대해 더 잘 이해가 되었습니다. 😉
⭐️ 참고한 곳
얄팍한 코딩사전 : 객체지향 디자인패턴 1
https://www.youtube.com/watch?v=lJES5TQTTWE&t=1s
https://brownbears.tistory.com/574
https://kscory.com/dev/design-pattern/strategy
https://steady-coding.tistory.com/381
배워야 할 것이 더 많은 주니어 개발자입니다. 🐣
내용 전달보다는 정리를 목적으로 포스팅을 하고 있습니다.
잘못 된 내용이나 부족한 부분은 댓글로 주시면 감사드리겠습니다.