전략 패턴: 유연한 알고리즘 설계 방법론

전략 패턴(Strategy Pattern)은 행위 디자인 패턴 중 하나로, 관련된 알고리즘 패밀리를 정의하고 각각을 캡슐화하여 상호 교체 가능하게 만듭니다. 이 패턴을 사용하면 알고리즘을 사용하는 클라이언트로부터 알고리즘을 독립적으로 변경할 수 있으며, 실행 중에 알고리즘을 동적으로 전환할 수 있습니다.

전략 패턴의 핵심 구성 요소:

  1. 전략 인터페이스(Strategy Interface): 모든 알고리즘이 구현해야 하는 공통 인터페이스를 정의합니다.
  2. 구체적인 전략 클래스(Concrete Strategy): 전략 인터페이스를 구현하는 실제 알고리즘 클래스입니다.
  3. 컨텍스트(Context): 전략 인터페이스를 사용하여 특정 전략 객체를 관리하고 실행합니다.

구현 예제:

검색 시스템에서 다양한 검색 방식(선형 검색, 이진 검색)을 구현하는 예제를 살펴보겠습니다.

먼저, 검색 전략 인터페이스를 정의합니다:

public interface SearchStrategy {
    int search(int[] dataset, int target);
}

다음으로, 두 가지 구체적인 검색 전략 클래스를 구현합니다:

public class LinearSearchStrategy implements SearchStrategy {
    @Override
    public int search(int[] dataset, int target) {
        for (int i = 0; i < dataset.length; i++) {
            if (dataset[i] == target) {
                return i;
            }
        }
        return -1;
    }
}

public class BinarySearchStrategy implements SearchStrategy {
    @Override
    public int search(int[] dataset, int target) {
        int left = 0;
        int right = dataset.length - 1;
        
        while (left <= right) {
            int mid = left + (right - left) / 2;
            
            if (dataset[mid] == target) {
                return mid;
            }
            
            if (dataset[mid] < target) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        
        return -1;
    }
}

이제 검색 컨텍스트 클래스를 구현합니다:

public class SearchContext {
    private SearchStrategy searchStrategy;
    
    public SearchContext(SearchStrategy searchStrategy) {
        this.searchStrategy = searchStrategy;
    }
    
    public void setSearchStrategy(SearchStrategy searchStrategy) {
        this.searchStrategy = searchStrategy;
    }
    
    public int performSearch(int[] dataset, int target) {
        return searchStrategy.search(dataset, target);
    }
}

마지막으로, 클라이언트 코드에서 필요에 따라 다양한 검색 전략을 사용할 수 있습니다:

public class SearchDemo {
    public static void main(String[] args) {
        int[] data = {1, 3, 5, 7, 9, 11, 13, 15};
        int targetValue = 7;
        
        SearchContext searchContext = new SearchContext(new LinearSearchStrategy());
        int result = searchContext.performSearch(data, targetValue);
        System.out.println("선형 검색 결과: " + (result != -1 ? "요소가 인덱스 " + result + "에서 발견됨" : "요소를 찾을 수 없음"));
        
        // 이진 검색 전략으로 전환
        searchContext.setSearchStrategy(new BinarySearchStrategy());
        result = searchContext.performSearch(data, targetValue);
        System.out.println("이진 검색 결과: " + (result != -1 ? "요소가 인덱스 " + result + "에서 발견됨" : "요소를 찾을 수 없음"));
    }
}

이 예제에서 SearchContext가 컨텍스트 역할을 수행하며 SearchStrategy 인터페이스에 의존합니다. LinearSearchStrategyBinarySearchStrategy는 구체적인 전략 구현체입니다. 클라이언트 코드는 SearchContext를 통해 다양한 검색 전략을 사용할 수 있으며, 검색 알고리즘의 변경이 클라이언트 코드에 영향을 주지 않습니다. 이는 개방-폐쇄 원칙(확장에는 열려 있고, 수정에는 닫혀 있음)을 준수하는 설계 방식입니다.

전략 패턴은 조건문(if-else 또는 switch-case)을 사용하여 다양한 알고리즘을 구현하는 대신, 알고리즘을 캡슐화하여 코드의 가독성과 유지보수성을 높이는 데 효과적입니다.

태그: 디자인 패턴 객체 지향 전략 패턴 알고리즘 소프트웨어 설계

7월 11일 02:30에 게시됨