수정 된 전략 디자인 패턴


11

나는 최근에 디자인 패턴을 조사하기 시작했고, 코딩하는 것 중 하나는 작은 차이를 제외하고 전략 패턴에 완벽하게 맞을 것입니다.

기본적으로 내 알고리즘 중 일부 (모두는 아님)에는 추가 매개 변수가 필요합니다.

그래서 나는

  • 계산 메소드를 호출 할 때 추가 매개 변수를 전달하십시오.

또는

  • ConcreteAlgorithm 클래스 내에 변수로 변수를 저장하고 알고리즘을 호출하기 전에 업데이트 할 수 있습니다.

이 요구에 맞는 디자인 패턴이 있습니까 / 전략 패턴을 고수하면서 어떻게 구현할 수 있습니까?

클라이언트 객체를 모든 알고리즘에 전달하고 거기에 변수를 저장 한 다음 특정 알고리즘에 필요할 때만 사용하는 것을 고려했습니다. 그러나 나는 이것이 다루기 힘들며 전략 패턴의 요점을 무너 뜨린다 고 생각합니다.

분명히 Java로 구현하고 있으므로 선택적 매개 변수가 없습니다 (이를 잘 해결할 것입니다).


C ++에서와 같은 선택적 매개 변수는 여러 오버로드 된 메소드를 정의하기위한 단축형이므로 아무것도 해결하지 못합니다.
maaartinus

사용하기 전에 매개 변수를 변경 해야하는 곳에 추가 매개 변수를 저장하지 않으려 고 노력했습니다. 이렇게하면 ConcreteAlgorithm을 상태 저장 상태로 만들 수 있으므로 다른 메서드 나 스레드로 쉽게 전달할 수 없습니다. 또한 매개 변수 설정을 잊어 버리기가 너무 쉽습니다.
maaartinus

답변:


5

Samuel, 각 전략이 하나의 공통 클래스로 취하는 매개 변수를 캡슐화 한 다음 해당 공통 매개 변수 클래스를 확장하여 일부 전략에 특별히 필요한 동작을 추가 할 수 있습니까?

예 :

StrategyParameter //Base strategy parameter that most of the strategies need
        ^
        |
        |
SpecialStrategyParameter // will be used for strategies that need more parameter

그런 다음 전략 계층 구조를 다음과 같이 정의하십시오.

Interface MyStrategy {
   void myStrategyMethod(StrategyParameter parameter);
}

class MyNormalStrategy extends MyStrategy {
   void myStrategyMethod(StrategyParameter parameter) {
       //implement the logic here
   }
}

위의 전략을 다음과 같이 호출하십시오. myNormalStrategyInstance.myStrategyMethod(strategyParameter);

class MySpecializedStrategy extends MyStrategy {
   void myStrategyMethod(StrategyParameter parameter) {
       //implement the logic here
   }
}

SpecialStrategyParameter대신 다음과 같이 인스턴스를 전달하여 위 전략을 호출하십시오 .mySpecializedStrategy.myStrategyMethod(specialStrategyParameter);

명확하지 않은 경우 업데이트하십시오. 기꺼이 설명 / 명확하게하겠습니다.


2
-1은 다운 캐스트가 필요하고 디자인 캡슐화를 중단합니다. 문제의 디자인이 개선되었지만이 고양이를 껍질을 벗기는 더 좋은 방법이 있습니다.
tallseth

@tallseth 나도 다운 캐스트를 본다. 그러나 나는 더 좋은 방법을 보지 못한다. 더 나은 해결책을 알려 주시겠습니까? 기사 또는 무언가?
Narek

사실 맞아요. @ Jordão는 우리가 질문에 대한 세부 사항을 바탕으로 내가 선호하는 답변을 가지고 있습니다. 그 대답은 전략 패턴의 강점에 달려 있습니다. 이 답변의 접근 방식을 취했다면 StrategyParameterDTO와 마찬가지로 가능한 모든 매개 변수를 포함 하고 싶습니다 . 전략의 일부 구현은이를 무시할 수 있습니다. 어떤 경우에는 이것이 최선의 방법입니다. 이러한 종류의 문제에 대한 맥락은 왕입니다.
tallseth

4

당신은 당신의 전략 을 명확히해야 합니다 .

알고리즘 사용 방법에 따라 다릅니다 . 클라이언트 클래스가 서로 다른 전략 구현을 상호 교환 가능하게 사용하려면 모두 공통된 추상화 가 필요합니다 . 그들이 동일한 인터페이스를 따르지 않는다면, 당신이 필요한 것은 다른 추상화 일 것 입니다.

나는 구성에 대한 구체적인 클래스를 매개 변수화하기 전에 구성 가능한 전략을 사용했습니다 .

interface Strategy {
  int calculate();
}

class ConcreteStrategyThatNeedsAParameter implements Strategy {
  private final int param;
  public ConcreteStrategyThatNeedsAParameter(int param) {
    this.param = param;
  }
  public int calculate() { 
    // uses param...
  }
}

이제 누군가가 여전히이 클래스의 인스턴스를 작성하여 클라이언트에게 전달해야합니다. 그러나 클라이언트는 여전히 Strategy인터페이스 에 대해서만 알아야합니다 .

전략 방법 이 매개 변수를 사용하는 경우에도 작동 하지만 클라이언트 해당 매개 변수를 알고 작동 하는 모든 구현으로 전달합니다 .


클라이언트는 매개 변수를 제공하기위한 컨텍스트를 가진 클라이언트입니다.
andyczerwonka

1

인터페이스에 서명이 명확하게 정의되어있는 한 여전히 전략 패턴을 준수합니다.

작성된 패턴은 여전히 ​​예상되는 동작을 나타내는 절대적으로 가장 간단한 형식이므로 원래 의도를 유지하는 한 패턴을 꾸밀 수 있습니다. 물론 패턴을 따르고 싶다고 가정합니다. 맞지 않거나 패턴이 있기 때문에 패턴을 사용하는 것이 중요하지 않지만 귀하의 경우에는 괜찮습니다.


0

peakit에서 제공 한 위의 답변을 확장하면 추상화를 사용할 수 있습니다. 여기 peakit의 코드를 사용하고 있습니다-

인터페이스 MyStrategy { abstract void myStrategyMethod (StrategyParameter parameter); }

MyNormalStrategy 클래스 MyStrategy 확장 {public override void myStrategyMethod (StrategyParameter parameter) {// 논리 구현}}

MySpecializedStrategy 클래스 MyStrategy 확장 {public override void myStrategyMethod (StrategyParameter parameter, ExtraStrategyParameter extraParameter) {// 논리를 구현 함} }

질문을 올바르게 이해하면 특정 알고리즘에 추가 매개 변수를 전달하고 싶습니까? 이것이 당신이 찾고있는 것이라면 알려주십시오.


0

디자인 패턴 책을 살펴보면 전달 된 매개 변수를 거의 사용하지 않거나 전혀 사용하지 않는 일부 SimpleStrategy가 존재하거나 매개 변수가 단일 크기 적합 / 모두 공통 곱셈기라는 것은 잘못된 것이 아닙니다. 여기서 디자인 선택은 사용하지 않는 추가 처리 측면에서 이것이 당신을 해칠 지 여부입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.