제 발표 내용을 통해 전략패턴에 대해 완벽하게 이해하는 것 보다는 전략패턴이 어떤 느낌인가? 라는 정도만 감을 잡는데 도움이 되셨으면 좋겠습니다 !
전략 & 패턴의 뜻
- 전략 : 특정한 목표를 수행하기 위한 행동 계획을 뜻함
- 패턴 : 되풀이 되는 사건이나 물체의 형태를 가리킨다.
디자인패턴이란?
- 객체지향 설계는 소프트웨어로 해결하고자 하는 문제를 다루게 되면서 동시에 재설계가 없거나 재설계를 최소화 하면서 요구사항 변화를 수용할 수 있도록 만들어 주었습니다.
- 그러한 과정에서 공통적으로(되풀이되는) 마주치는 문제(패턴)를 해결하는 방법을 뜻합니다.
- 디자인 패턴을 적용하면 상황에 맞는 올바른 설계를 더 빠르게 적용할 수 있으며 각 패턴의 장단점을 통해 설계를 선택하는데 도움을 얻을 수 있습니다.
그래서 전략패턴이 뭘까?
- 많은 디자인 패턴중에 하나로 객체가 할 수 있는 행위를 각각 전략으로 만들어 놓고 사용하면서 동적으로 전략수정이 가능한 패턴을 말합니다.
- 런타임 중에 전략이 동적으로 변경이 가능합니다.
- 전략패턴은 if-else로 구성된 코드 블록이 비슷한 기능을 수행하거나 동일한 기능의 알고리즘을 변경해야 하는 경우에 전략패턴을 적용할 수 있습니다.
전략패턴의 장점
- 런타임에서 객체 내부에서 사용되는 알고리즘을 변경할 수 있습니다.
- 알고리즘을 사용하는 코드와 알고리즘을 구현하는 코드를 분리할 수 있습니다.
- OCP를 준수하며 Context를 변경하지 않고도 새로운 전략을 도입할 수 있습니다.
전략패턴의 단점
- 알고리즘이 몇 개 없고 변경되는 일도 거의 없는 경우에는 전략패턴의 도입이 오히려 복잡성을 증가시킬 수 있습니다.
- 클라이언트가 적절한 전략을 선택하기 위해 각각의 차이점을 인지하고 있어야 합니다.
- Strategy, Context간 통신 오버헤드가 발생합니다.
시나리오
예제
검색기능을 만들고 있는데 현재 전체검색과 이미지 검색만 제공하고 있다.
V1 - 기본
검색엔진을 만들고 있는데 현재 전체검색과 이미지 검색만 제공하고 있다.
class AllSearch { public void search() { System.out.println("전체검색"); } } class ImageSearch { public void search() { System.out.println("이미지 검색"); } } class Main { public static void main(String[] args) {/ AllSearch allSearch = new AllSearch(); ImageSearch imageSearch = new ImageSearch(); allSearch.search(); imageSearch.search(); } }
V2 - 상속
지도 검색도 추가할 계획이고 앞으로 더 많은 검색엔진을 개발할 계획인데 클래스를 계속 만들어 관리하면 유지보수가 힘들어 질 것 같다.
상속을 통해 조금 더 편리하게 변경할 수 있게 되었다.
public abstract class Search { public abstract void search(); } class AllSearch extends Search { @Override public void search() { System.out.println("전체검색"); } } class ImageSearch extends Search { @Override public void search() { System.out.println("이미지 검색"); } } public class Main { public static void main(String[] args) { Search searchMachine = new AllSearch(); searchMachine.search(); } }
V3 - 문제발생
하지만 여기서 각 검색엔진에 정렬 기능이 추가된다면?
정렬 기능 추가해주지 뭐 !
정렬기능 까지 추상 메서드를 추가하여 각 검색별로 구현을 해주었는데.. 전체검색과 지도검색의 정렬을 퀵정렬로 수정해야 한다면?
병합정렬을 이용하고 있는 검색엔진 클래스에는 모두 수정을 해줘야 한다는 단점이 존재한다. 현재는 두개지만 더 많은 검색엔진에 병합정렬이 사용되고 있다면 더 많은 클래스에 수정이 일어나게 된다.
public abstract class Search { public abstract void search(); public abstract void sort(); } // 전체검색 public class AllSearch extends Search { @Override public void search() { System.out.println("전체검색"); } @Override public void sort() { System.out.println("병합정렬로 합니다"); } } // 이미지검색 public class ImageSearch extends Search { @Override public void search() { System.out.println("이미지 검색"); } @Override public void sort() { System.out.println("퀵정렬로 합니다."); } } // 지도검색 public class MapSearch extends Search { @Override public void search() { System.out.println("지도검색"); } @Override public void sort() { System.out.println("병합정렬로 합니다."); } }
V4 - 전략사용
이제 동일 계열의 알고리즘군 정하고 각 알고리즘을 캡슐화를 하자 !
검색에 대한 전략을 만들고 전체, 이미지, 지도 검색등의 행위를 만들고 정렬도 마찬가지로 정렬에 대한 전략을 만든다음 퀵정렬, 병합정렬 등의 정렬행위를 만들어 준다.
검색엔진을 만들어 생성할 때 각각의 전략을 생성하여 전략에 행위를 실행하도록 만들어준다.

public class Main { public static void main(String[] args) { SearchMachine searchMachine = new SearchMachine(new AllSearch(), new QuickSort()); searchMachine.search(); searchMachine.sort(); } }
V5 - 전략수정
전략을 수정해보자 !
세터를 이용해서 전략을 동적으로 수정할 수 있도록 만들어보자 !
public class SearchMachine { private SearchStrategy searchStrategy; private SortStrategy sortStrategy; public SearchMachine(SearchStrategy searchStrategy, SortStrategy sortStrategy) { this.searchStrategy = searchStrategy; this.sortStrategy = sortStrategy; } public void search() { searchStrategy.search(); } public void sort() { sortStrategy.sort(); } // 세터추가 public void setSearchStrategy(SearchStrategy searchStrategy) { this.searchStrategy = searchStrategy; } // 세터추가 public void setSortStrategy(SortStrategy sortStrategy) { this.sortStrategy = sortStrategy; } } public class Main { public static void main(String[] args) { SearchMachine searchMachine = new SearchMachine(new AllSearch(), new MergeSort()); searchMachine.search(); searchMachine.sort(); // 전략수정 searchMachine.setSearchStrategy(new MapSearch()); searchMachine.setSortStrategy(new QuickSort()); searchMachine.search(); searchMachine.sort(); } }
- 동적으로 “전략"을 변경하며 사용할 수 있게 되었으며 새로운 전략을 Context 수정 없이 추가할 수 있게 되며 OCP를 만족하게 됩니다.
전략패턴은 어디에서 사용되고 있을까?
자바에서 사용되고 있는 전략패턴은 어떤게 있을까?
- 많이 사용하고있는 자바 Comparator compare메서드에서 사용되고 있습니다. 그때그때 마다 저희가 새롭게 정의한 “전략"으로 정렬을 수행할 수 있도록하여 만들 수 있죠 🙂
// 나이순 정렬 class User implements Comparator<User> { String name; int age; @Override public int compare(User u) { return this.age - u.age; } }