전략(Strategy) 패턴
**전략 패턴(Strategy Pattern)**은 행위를 캡슐화하여 동적으로 변경할 수 있도록 만드는 행동 디자인 패턴입니다. 이 패턴에서는 여러 알고리즘을 각각 클래스로 캡슐화하고, 상황에 따라 유연하게 알고리즘을 교체할 수 있습니다. 객체는 동일한 인터페이스를 사용해 서로 다른 알고리즘을 실행합니다.
문제점: 다양한 알고리즘을 사용하는 코드의 복잡성
예를 들어, 정렬 알고리즘을 여러 방식으로 구현해야 하는 애플리케이션을 생각해봅시다.
if-else
나 switch
구문으로 알고리즘을 선택하게 되면 코드가 복잡해지고 확장성이 떨어집니다.
class Sorter {
public void sort(int[] arr, String type) {
if (type.equals("bubble")) {
bubbleSort(arr);
} else if (type.equals("quick")) {
quickSort(arr);
}
}
private void bubbleSort(int[] arr) {
System.out.println("Bubble Sort");
// 버블 정렬 로직...
}
private void quickSort(int[] arr) {
System.out.println("Quick Sort");
// 퀵 정렬 로직...
}
}
public class Main {
public static void main(String[] args) {
Sorter sorter = new Sorter();
sorter.sort(new int[]{5, 3, 8, 1}, "quick");
}
}
문제점
- 유연성 부족: 새로운 정렬 알고리즘을 추가할 때 기존 코드를 수정해야 합니다.
- 단일 책임 원칙 위반: Sorter 클래스가 여러 정렬 알고리즘을 모두 관리합니다.
- 테스트 어려움: 각 알고리즘이 직접 코드에 묶여있어 개별 테스트가 어렵습니다.
해결 방법: 전략 패턴 적용
전략 패턴은 여러 알고리즘을 각각의 클래스로 분리하고, 동일한 인터페이스를 통해 알고리즘을 실행합니다. 이로써 클래스 간의 결합도를 낮추고, 새로운 알고리즘을 쉽게 추가할 수 있습니다.
Strategy 인터페이스 정의
interface SortStrategy {
void sort(int[] arr);
}
구체적인 알고리즘 클래스 구현
class BubbleSort implements SortStrategy {
@Override
public void sort(int[] arr) {
System.out.println("Performing Bubble Sort");
// 버블 정렬 로직...
}
}
class QuickSort implements SortStrategy {
@Override
public void sort(int[] arr) {
System.out.println("Performing Quick Sort");
// 퀵 정렬 로직...
}
}
Context 클래스 구현
class Sorter {
private SortStrategy strategy;
public void setStrategy(SortStrategy strategy) {
this.strategy = strategy;
}
public void sort(int[] arr) {
strategy.sort(arr);
}
}
클라이언트 코드
public class Main {
public static void main(String[] args) {
Sorter sorter = new Sorter();
// 버블 정렬 사용
sorter.setStrategy(new BubbleSort());
sorter.sort(new int[]{5, 3, 8, 1});
// 퀵 정렬 사용
sorter.setStrategy(new QuickSort());
sorter.sort(new int[]{5, 3, 8, 1});
}
}
Strategy 패턴의 동작 원리
- Context 객체는 알고리즘을 수행하지만, 실제 알고리즘의 구현은 전략 객체에 위임합니다.
- 전략 객체는 공통된 인터페이스를 구현하며, 서로 교체 가능하게 설계됩니다.
- 클라이언트는 전략 객체를 동적으로 선택하여 다양한 알고리즘을 유연하게 사용할 수 있습니다.
Strategy 패턴의 장단점
장점
- 유연한 확장: 새로운 알고리즘을 추가할 때 기존 코드를 수정할 필요가 없습니다.
- 단일 책임 원칙 준수: 각 알고리즘은 별도의 클래스에 정의되므로 코드의 책임이 분리됩니다.
- 유연한 교체: 런타임에 알고리즘을 쉽게 교체할 수 있습니다.
단점
- 클래스 수 증가: 각 알고리즘을 별도의 클래스로 정의해야 하므로 클래스가 많아질 수 있습니다.
- 전략 선택의 복잡성: 클라이언트가 적절한 전략을 선택해야 합니다.
결론
**전략 패턴(Strategy Pattern)**은 알고리즘을 캡슐화하여 교체 가능하게 설계하는 강력한 패턴입니다. 이 패턴을 사용하면 유연하게 알고리즘을 추가하고 교체할 수 있으며, 코드의 재사용성과 유지보수성이 높아집니다. 정렬 알고리즘, 결제 시스템, 게임 AI 등 동적으로 알고리즘을 변경해야 하는 다양한 상황에서 사용됩니다.
하지만, 클래스 수가 많아질 수 있고 클라이언트가 직접 전략을 선택해야 하므로 복잡도가 증가할 수 있습니다. 따라서 상황에 맞게 적절히 사용하는 것이 중요합니다.