Strategy Pattern

개념
- 알고리즘을 교체해서 동일한 문제를 다른 방법으로 해결 하는 패턴

I. 의도

     다양한 알고리즘이 존재하면 이들 각각을 하나의 클래스로 캡슐화해 알고리즘의 대체가 가능하도록 한다. 클라이언트와 독립적인 다양한 알고리즘으로 변형할 수 있다. 알고리즘이 변경되어도 클라이언트는 변경할 필요없다

    정의 : 알고리즘을 교체해서 동일한 문제를 다른 방법으로 해결 하는 패턴
           : 알고리즘군을 정의하고 각각을 캡슐화하여 바꿔 쓸 수 있게 만듦, 레지스터할당방법, 명령어 집합 스캐듈링 전략

II. 활용

  • 행위들이 조금씩 다를 뿐 개념적으로 관련된 많은 클래스들이 존재하는 경우, 각각의 서로 다른 행위별로 클래스를 작성한다. 즉, 개념에 해당하는 클래스는 하나만 정의하고 서로 다른 행위들을 별도의 클래스로 만드는 것이다
  • 알고리즘의 변형이 필요한 경우에 사용할 수 있다
  • 사용자가 모르고 있는 데이터를 사용해야 하는 알고리즘이 필요할 때
  • 많은 행위를 정의하기 위해 클래스 안에 복잡한 다중 조건문을 사용해야 하는 경우 선택문보다는 starategy클래스 이용이 바람직       

III. 결과

  • 관련 알고리즘의 군을 형성한다. 상속을 통해 알고리즘 공통의 기능성을 추출하고 재사용할 수 있다
  • 서브클래싱을 사용하지 않는 다른 방법이다. 상속은 다양한 알고리즘이나 행위를 지원하는 또 다른 방법이다 – 알고리즘을 starategy 클래스로 독립시키면 context와 무관하게 알고리즘을 변형/이해/확장이 용이하다
  • strategy는 조건문을 없앨 수 있다
  • 구현의 선택이 가능하다 – 동일한 행위에 대해 다른 구현을 제공할 수 있다
  • 사용자는 서로 다른 전략을 알고 있어야 한다 – 클라이언트가 서로 다른 행위의 특성을 알고 있는 경우 starategy 사용
  • strategy와 context 클래스 간에 과다한 메시지가 전송된다
  • 객체 수가 증가한다

관련 패턴: starategy 객체는 작은 규모의 클래스들이므로 flyweight 패턴으로 정의하는 것이 좋다

 

 Strategy: 제공하는 모든 알고리즘에 대한 공통의 오퍼레이션들을 인터페이스로 정의한다. Context 클래스는 ConcreteStrategy 클래스에 정의한 인터페이스를 통해서 실제 알고리즘을 사용한다.

  • ConcreteStrategy: Strategy 인터페이스를 실제 알고리즘으로 구현한다.
  • Context: ConcreteStrategy 객체가 무엇인지 구체화한다. 즉, Strategy 객체에 대한 참조자를 관리하고, 실제로는 Strategy 서브클래스의 인스턴스를 갖고 있음으로써 구체화한다. 또한 Strategy 가 자료에 접근해가는데 필요한 인터페이스를 정의한다.

 

 

소스코드

 

/StrategyExample test application

 

class StrategyExample {

 

    public static void main(String[] args) {

 

        Context context;

 

        // Three contexts following different strategies

        context = new Context(new ConcreteStrategyAdd());

        int resultA = context.executeStrategy(3,4);

 

        context = new Context(new ConcreteStrategySubtract());

        int resultB = context.executeStrategy(3,4);

 

        context = new Context(new ConcreteStrategyMultiply());

        int resultC = context.executeStrategy(3,4);

    }

}

 

// The classes that implement a concrete strategy should implement this

 

// The context class uses this to call the concrete strategy

interface Strategy {

    int execute(int a, int b);

}

 

// Implements the algorithm using the strategy interface

class ConcreteStrategyAdd implements Strategy {

 

    public int execute(int a, int b) {

        System.out.println("Called ConcreteStrategyAdd's execute()");

        return a + b;  // Do an addition with a and b

    }

}

 

class ConcreteStrategySubtract implements Strategy {

 

    public int execute(int a, int b) {

        System.out.println("Called ConcreteStrategySubtract's execute()");

        return a - b;  // Do a subtraction with a and b

    }

}

 

class ConcreteStrategyMultiply implements Strategy {

 

    public int execute(int a, int b) {

        System.out.println("Called ConcreteStrategyMultiply's execute()");

        return a * b;   // Do a multiplication with a and b

    }   

}

 

// Configured with a ConcreteStrategy object and maintains a reference to a Strategy object

class Context {

 

    private Strategy strategy;

 

    // Constructor

    public Context(Strategy strategy) {

        this.strategy = strategy;

    }

 

    public int executeStrategy(int a, int b) {

        return strategy.execute(a, b);

    }

}

댓글