[JAVA/디자인패턴] Strategy Pattern, 전략 패턴

2023. 10. 5. 14:32
반응형

Strategy Pattern

 

 

https://en.wikipedia.org/wiki/Strategy_pattern

 

같은 종류의 작업을 하는 알고리즘을 정의, 각 알고리즘을 캡슐화, 그리고 알고리즘들을 바꿔 유동적으로 사용할 수 있도록 하는 디자인패턴.알고리즘을 사용하는 클라이언트로 부터 독립적으로 알고리즘을 바꿔서 적용시킬 수 있도록 한다.

클라이언트에 모든 알고리즘을 포함시키는 것은 클라이언트 코드의 양이 늘어나고 복잡해진다. 이는 유지 보수가 어려워지며, 새로운 알고리즘 추가를 하려면 기존 코드를 수정해야 하는 문제가 있다.

 

Context : 캡슐화된 알고리즘을 멤버 변수로 포함하며, 알고리즘을 교환해서 적용시킬 수 있다.

Strategy : 컴파일 시점에서 사용하는 캡슐화된 알고리즘, 실제 구현은 하위 Strategy(n) 클래스에 위임, 인터페이스 혹은 추상클래스로 구현한다.

Strategy(n) : 실행 시점에 적용될 알고리즘을 캡슐화, Context에서 실행될 알고리즘을 구현한다.

 

 

 


Strategy Pattern를 적용한 정렬

 

 

상명대학교 컴퓨터과학과 조용주 교수님

Strategy 패턴을 적용한 정렬 알고리즘을 구현해보도록 하겠다.

다이어그램의 사항은, Strategy 패턴의 하기 사항처럼 매칭된다.

[Sorter -> Context], [SortAlg -> Strategy], [BubbleSortAlg/InsertionSortAlg/SelectionSortAlg -> Strategy(n)]

 

목적은 Sorter 클래스에서, 상황에 따라서 버블 정렬, 선택 정렬, 삽입 정렬을 교체해가면서 사용할 수 있도록 Strategy Pattern을 적용하는 것이다.

 

 

 

Context 작성

public class Sorter {
    private SortAlgs soltAlgs;

    public Sorter(SortAlgs soltAlgs){

        this.soltAlgs = soltAlgs;
    }

    public void setSortAlgs(SortAlgs soltAlgs){

        this.soltAlgs = soltAlgs;
    }

    public void sort(int[] data) {
        this.soltAlgs.sort(data);
    }
}

Sorter 클래스이다. 메서드로는 아래의 사항들이 포함되어있다.

1. 같은 종류의 알고리즘을 실행시키는 operator에 해당하는 sort()

2. 알고리즘의 방식을 교환시키는 setSortAlgs()

 

 

 

Strategy 작성

public interface SortAlgs {

    void sort(int[] data);

}

Strategy에 해당하는 SortAlgs 클래스이다.

인터페이스로 정의했으며, sort()는 정렬 기능을 한다는 명세를 나타낸다.

 

 

 

Strategy(n) (구현체) 작성

public class BubbleSortAlg implements SortAlgs {
    @Override
    public void sort(int[] data) {
        for (int i = 0; i < data.length - 1; i++) {
            for (int j = 0; j < data.length - 1; j++) {
                if (data[j] > data[j + 1]) { // swap
                    int temp = data[j];
                    data[j] = data[j + 1];
                    data[j + 1] = temp;
                }
            }
        }
    }
}
public class InsertionSortAlg implements SortAlgs {
    @Override
    public void sort(int[] data) {
        for (int i = 1; i < data.length; i++) {
            int key = data[i];
            int j;
            for (j = i - 1; j >= 0 && data[j] > key; j--) {
                data[j + 1] = data[j];
            }
            data[j + 1] = key;
        }
    }
}
public class SelectionSortAlg implements SortAlgs {
    @Override
    public void sort(int[] data) {
        for (int i = 0; i < data.length - 1; i++) {
            int minIdx = i;
            for (int j = i + 1; j < data.length; j++) {
                if (data[j] < data[minIdx]) { // swap
                    minIdx = j;
                }
            }
            int temp = data[minIdx];
            data[minIdx] = data[i];
            data[i] = temp;
        }
    }
}

위의 Strategy를 실제로 구현하는 클래스들이다.

이제 Context에서는 Strategy의 종류를 위 세 가지의 정렬 알고리즘으로 변경하면서 사용할 수 있게 된다.

 

 

 

 

 

 

 

public class Main {
    static void printInts(int[] data) {
        for (int i : data) {
            System.out.print(i + " ");
        }
        System.out.println();
    }
    public static void main(String[] args) {
        int[] data = { 23, 22, 22, 26, 24, 24, 26, 25, 23, 27, 32, 30, 35, 34, 32 };
       
        SortAlgs si = new InsertionSortAlg();
        Sorter sorter = new Sorter(si);
        si.sort(data);
        printInts(data);

        sorter.setSortAlgs(new SelectionSortAlg());
        si.sort(data);
        printInts(data);

        sorter.setSortAlgs(new InsertionSortAlg());
        si.sort(data);
        printInts(data);
    }
}

다음 사용 예시를 보면, Context에 해당하는 Sorter의 Strategy(알고리즘)를 Strategy(n)(Insertion, Selection)으로 변경해가면서 사용하고 있다.

Straegy 패턴을 적용하면 같은 종류인 각각의 알고리즘의 내부 내용을 알지 않아도 되어 캡슐화의 의미에 부합하며, 새로운 알고리즘을 추가하더라도 새로운 Strategy 구현체를 추가하여 교체해주기만 하면 되어 기존 사용하던 알고리즘의 코드를 바꿀 필요가 없다.

 

반응형

BELATED ARTICLES

more