문제

템플릿 메소드 패턴과 전략 패턴의 차이점이 무엇인지 설명해 주실 수 있나요?

내가 알 수있는 한, 그것들은 99% 동일하다. 유일한 차이점은 템플릿 메소드 패턴이 기본 클래스와 같은 추상 클래스를 가지고 있고 전략 클래스는 각 콘크리트 전략 클래스에서 구현 된 인터페이스를 사용한다는 것입니다.

그러나 지금까지는 고객 정확히 같은 방식으로 소비된다는 우려가 있습니다. 이것이 맞나요?

도움이 되었습니까?

해결책

이 둘의 주요 차이점은 콘크리트 알고리즘을 선택할 때입니다.

이랑 템플릿 메소드 패턴 이런 일이 발생합니다 컴파일 타임 ~에 의해 서브 클래싱 템플릿. 각 서브 클래스는 템플릿의 추상 방법을 구현하여 다른 콘크리트 알고리즘을 제공합니다. 클라이언트가 템플릿의 외부 인터페이스의 메소드를 호출하면 템플릿은 알고리즘을 호출하는 데 필요한대로 추상 메소드 (내부 인터페이스)를 호출합니다.

class ConcreteAlgorithm : AbstractTemplate
{
    void DoAlgorithm(int datum) {...}
}

class AbstractTemplate
{
    void run(int datum) { DoAlgorithm(datum); }

    virtual void DoAlgorithm() = 0; // abstract
}

대조적으로, 전략 패턴 알고리즘을 선택할 수 있습니다 실행 시간 ~에 의해 방지. 콘크리트 알고리즘은 생성자 또는 세터 방법에 매개 변수로 전략으로 전달되는 별도의 클래스 또는 함수에 의해 구현됩니다. 이 매개 변수에 대해 선택된 알고리즘은 프로그램의 상태 또는 입력에 따라 동적으로 다를 수 있습니다.

class ConcreteAlgorithm : IAlgorithm
{
    void DoAlgorithm(int datum) {...}
}

class Strategy
{
    Strategy(IAlgorithm algo) {...}

    void run(int datum) { this->algo.DoAlgorithm(datum); }
}

요약해서 말하자면:

  • 템플릿 메소드 패턴 : 컴파일 타임 알고리즘 선택 서브 클래싱
  • 전략 패턴 : 런타임 알고리즘 선택 방지

다른 팁

템플릿 패턴은 특정 작업에 다른 다양한 원시적 동작으로 정의 될 수있는 일부 불변 거동이있을 때 사용됩니다. 추상 클래스는 변하지 않는 동작을 정의하는 반면 구현 클래스는 종속 방법을 정의했습니다.

전략에서 행동 구현은 독립적입니다. 각 구현 클래스는 동작을 정의하고 그 사이에 공유되는 코드가 없습니다. 둘 다 행동 패턴이며, 따라서 고객과 거의 같은 방식으로 소비됩니다. 일반적으로 전략에는 단일 공개 방법이 있습니다 execute() 방법, 템플릿은 일련의 공개 방법과 서브 클래스가 구현 해야하는 지원 개인 프리미티브 세트를 정의 할 수 있습니다.

두 패턴은 쉽게 함께 사용할 수 있습니다. 여러 구현이 템플릿 패턴을 사용하여 구현 된 전략 제품군에 속하는 전략 패턴이있을 수 있습니다.

두 패턴의 클래스 다이어그램이 차이점을 보여주고 있다고 생각합니다.

전략
클래스 내에서 알고리즘을 캡슐화합니다
이미지 링크 enter image description here

템플릿 메소드
알고리즘의 정확한 단계를 서브 클래스로 연기
이미지 링크 enter image description here

아마도 템플릿 메소드 패턴을 의미 할 것입니다. 당신은 맞습니다. 그들은 매우 비슷한 요구를 제공합니다. 서브 클래스가 이러한 단계를 무시하여 일부 세부 사항을 변경하는 정의 된 단계를 가진 "템플릿"알고리즘이있는 경우 템플릿 메소드를 사용하는 것이 좋습니다. 전략의 경우 인터페이스를 만들어야하며 상속 대신 대표단을 사용합니다. 나는 그것이 조금 더 강력한 패턴이며 딥 의존성 반전 원리에 따라 더 나을 것입니다. 전략의 새로운 추상화를 명확하게 정의하기 때문에 템플릿 방법에 적용되지 않는 무언가를하는 방법입니다. 따라서이 추상화가 의미가 있다면 사용하십시오. 그러나 템플릿 방법을 사용하면 간단한 경우에 더 간단한 디자인을 제공 할 수 있으며 이는 또한 중요합니다. 어떤 단어가 더 잘 맞는지 고려하십시오 : 템플릿 알고리즘이 있습니까? 아니면 여기에서 전략의 추상화가있는 핵심 일입니다 - 무언가를하는 새로운 방법

템플릿 방법의 예 :

Application.main()
{
Init();
Run();
Done();
}

여기에서 당신은 신청서에서 물려 받고 이니, 실행 및 완료에서 정확히 무엇을 할 것인지 대체합니다.

전략의 예 :

array.sort (IComparer<T> comparer)

여기에서 비교기를 쓸 때 배열에서 상속받지 않습니다. 배열은 비교 알고리즘을 비교기로 위임합니다.

Difference between Strategy and Template Method Pattern Strategy vs Template method


유사점

전략과 템플릿 메서드 패턴은 서로 많은 유사점을 가지고 있습니다.개방-폐쇄 원칙을 충족하고 코드 변경 없이 소프트웨어 모듈을 쉽게 확장하기 위해 전략 및 템플릿 방법 패턴을 모두 사용할 수 있습니다.두 패턴 모두 해당 기능의 세부 구현과 일반 기능의 분리를 나타냅니다.그러나 제공하는 세분성 측면에서 약간 다릅니다.


차이점

다음은 이 두 가지 패턴을 연구하면서 관찰한 몇 가지 차이점입니다.

  1. 전략에서는 클라이언트와 전략의 커플 링이 더 느슨하지만 템플릿 방법에서는 두 모듈이 더 단단히 결합됩니다.
  2. 전략에서는 상황에 따라 추상 클래스가 사용될 수 있지만 대부분의 인터페이스가 사용될 수 있으며 콘크리트 클래스는 사용되지 않지만 템플릿 방법에서 대부분 추상 클래스 또는 콘크리트 클래스가 사용되면 인터페이스가 사용되지 않습니다.
  3. 전략 패턴에서, 일반적으로 클래스의 전체 동작은 인터페이스로 표시되며, 반면에, 템플릿 방법은 코드 복제를 줄이고 보일러 플레이트 코드는 기본 프레임 워크 또는 초록 ​​클래스에 정의됩니다.템플릿 메소드에는 기본 구현이있는 구체적인 클래스가있을 수 있습니다.
  4. 간단히 말해서, 전략 패턴에서 전체 전략 (알고리즘)을 변경할 수 있지만 템플릿 메소드에서는 몇 가지 사항 만 변경 (알고리즘의 일부)과 나머지는 변경되지 않은 상태로 남아 있습니다.템플릿 메소드에서 불변 단계는 추상 기본 클래스에서 구현되며, 변형 단계에는 기본 구현이 제공되거나 전혀 구현되지 않습니다.템플릿 메소드에서 구성 요소 디자이너는 알고리즘의 필요한 단계와 단계 순서를 의무화하지만 구성 요소 클라이언트는 이러한 단계의 일부를 확장하거나 교체 할 수 있습니다.

이미지는 다음에서 가져왔습니다. 한 입 크기의 블로그.

상속 대 응집 (IS-A 대 HAS-A). 같은 목표를 달성하는 두 가지 방법입니다.

이 질문은 선택간에 일부 상충 관계를 보여줍니다. 상속 대 집계

둘 다 매우 유사하며 둘 다 클라이언트 코드에 의해 비슷한 방식으로 소비됩니다. 위의 가장 인기있는 답변과 달리 둘 다 런타임에 알고리즘 선택을 허용합니다.

둘의 차이점은 전략 패턴 다른 구현이 원하는 결과를 달성하는 데 완전히 다른 방법을 사용할 수 있습니다. 템플릿 메소드 패턴 결과를 달성하는 데 사용되는 가장 중요한 알고리즘 ( "템플릿"메소드)을 지정합니다. 특정 구현 (하위 클래스)에 남은 유일한 선택은 상기 템플릿 메소드의 특정 세부 사항입니다. 이것은 템플릿 메소드가 하나 이상으로 호출하도록함으로써 수행됩니다. 요약 하위 클래스에 의해 추상적이지 않고 하위 클래스에 의해 무시되지 않는 템플릿 메소드와 달리 하위 클래스에 의해 재정의 된 방법 (즉, 구현).

클라이언트 코드는 전략 패턴을 사용하는 동안처럼 실행 시간에 결정할 수있는 콘크리트 하위 클래스 중 하나의 인스턴스를 가리키는 추상 클래스 유형의 참조/포인터를 사용하여 템플릿 메소드를 호출합니다.

템플릿 방법 :

  1. 그것은 기반입니다 계승
  2. 하위 클래스로 변경할 수없는 알고리즘의 골격을 정의합니다. 하위 클래스에서 특정 작업 만 재정의 할 수 있습니다
  3. 학부모 수업을 완전히합니다 알고리즘을 제어합니다 특정 단계 만 구체적인 클래스와 다릅니다
  4. 바인딩은 컴파일 시간에 수행됩니다

template_method 구조:

enter image description here

전략:

  1. 그것은 기반입니다 위임/구성
  2. 그것은 대상의 내장을 바꿉니다 방법 동작을 수정하여
  3. 익숙합니다 알고리즘 제품군 사이를 전환합니다
  4. 실행 시간에 객체의 동작을 완전히 변경합니다. 하나의 알고리즘을 실행 시간에 다른 알고리즘으로 교체합니다
  5. 바인딩은 실행 시간에 수행됩니다

전략 구조:

enter image description here

살펴보십시오 템플릿 메소드 그리고 전략 더 나은 이해를위한 기사.

관련 게시물:

JDK의 템플릿 디자인 패턴은 순서대로 실행할 메소드 세트를 정의하는 메소드를 찾을 수 없습니다.

전략 패턴의 실제 예

아니요, 반드시 같은 방식으로 소비되는 것은 아닙니다. "템플릿 메소드"패턴은 미래의 구현 자에게 "지침"을 제공하는 방법입니다. 당신은 그들에게 "모든 사람의 물건에는 사회 보장 번호가 있어야한다"고 말하고 있습니다 (사소한 예이지만 아이디어를 올바르게 만듭니다).

전략 패턴이 허용됩니다 다수의 가능한 구현이 들어오고 나갈 수 있습니다. 상속을 통해 (보통) 구현되는 것이 아니라 대신 호출자가 원하는 구현에서 통과하도록함으로써 구현됩니다. 예를 들어, 세금을 계산하는 여러 가지 방법 중 하나 (Nosalestax 구현 및 백분율 기반 재산 구현)가 제공 될 수 있습니다.

그래서 때로는 고객 실제로 어떤 전략을 사용할 것인지 알 것입니다. 에서와 같이

myShippingCalculator.CalculateTaxes(myCaliforniaSalesTaxImpl);

그러나 클라이언트는 템플릿 메소드를 기반으로 한 객체에 대해 결코 그렇게하지 않을 것입니다. 실제로 클라이언트는 객체가 템플릿 메소드를 기반으로하는 것을 알지 못할 수도 있습니다. 템플릿 메소드 패턴의 추상 방법은 보호 될 수 있으며,이 경우 클라이언트가 존재하는 것을 알지 못할 수도 있습니다.

나는 당신이 읽을 것을 제안합니다 이것 기사. 실제 사례의 차이점을 설명합니다.

기사에서 인용합니다

"구현 클래스는 템플릿 메소드 클래스에 따라 달라집니다. 이 종속성은 알고리즘의 일부 단계를 변경하려면 템플릿 메소드를 변경합니다. 다른 쪽에서 전략은 알고리즘을 완전히 캡슐화합니다. 알고리즘을 완전히 정의하기 위해 구현 클래스를 제공합니다. 따라서 변경 사항이 도착하면 이전에 서면으로 작성된 클래스의 코드를 변경해야합니다. 이것이 내가 수업을 설계하기위한 전략을 선택한 주된 이유였습니다.

템플릿 메소드의 한 가지 기능 중 하나는 템플릿 메소드가 알고리즘을 제어한다는 것입니다. 다른 상황에서는 좋은 일이 될 수 있지만 내 문제에서 이것은 수업을 설계하도록 제한했습니다. 다른 쪽에서 전략은 알고리즘의 단계를 제어하지 않아 완전히 다른 변환 방법을 추가 할 수 있습니다. 따라서 내 경우에는 전략이 구현에 도움이됩니다.

전략의 한 가지 단점은 코드 중복성이 너무 많고 코드 공유가 적다는 것입니다. 이 기사의 제시된 예에서 명백한 것처럼, 나는 4 개의 클래스에서 동일한 코드를 반복해서 반복해야합니다. 그러므로 모두에 공통적 인 단계 4와 같은 시스템의 구현이 변경되면 5 개의 클래스 모두에서이를 업데이트해야하기 때문에 유지하기가 어렵습니다. 다른 한편으로, 템플릿 방법에서는 슈퍼 클래스 만 변경할 수 있으며 변경 사항은 하위 클래스에 반영됩니다. 따라서 템플릿 방법은 클래스간에 매우 적은 양의 중복성과 많은 양의 코드 공유를 제공합니다.

전략을 통해 런타임에 알고리즘을 변경할 수 있습니다. 템플릿 메소드에서는 객체를 다시 시작해야합니다. 이 전략의 기능은 많은 유연성을 제공합니다. 디자인의 관점에서 하나는 상속보다 구성을 선호해야합니다. 따라서 전략 패턴을 사용하는 것도 개발을위한 주요 선택이되었습니다. "

템플릿 패턴은 전략 패턴과 유사합니다. 이 두 패턴은 범위와 방법론이 다릅니다.

전략은 발신자가 다른 유형의 세금을 계산하는 방법과 같은 전체 알고리즘을 변경할 수 있도록하는데, 템플릿 방법은 알고리즘의 단계를 변화시키는 데 사용됩니다. 이로 인해 전략은 더 거칠게 납치됩니다. 템플릿은 일련의 작업에서 더 미세한 제어를 허용하지만 이러한 세부 사항의 구현은 다양합니다.

다른 주요 차이점은 전략이 대표단을 사용하고 템플릿 메소드는 상속을 사용한다는 것입니다. 전략에서 알고리즘은 주제가 참조 할 다른 xxxStrategy 클래스에 위임되지만 템플릿을 사용하면 기본을 서브 클래스하고 변경하여 변경 방법을 재정의합니다.

~에서 http://cyruscrypt.blogspot.com/2005/07/template-vs-strategy-patterns.html

전략 패턴에서 서브 클래스가 쇼를 진행하고 있으며 알고리즘을 제어합니다. 여기서 코드는 서브 클래스에 중복됩니다. 알고리즘에 대한 지식과 구현 방법은 많은 클래스에 배포됩니다.

템플릿 패턴에서 기본 클래스에는 알고리즘이 있습니다. 서브 클래스 간의 재사용을 극대화합니다. 알고리즘은 한 곳에 있기 때문에 기본 클래스는이를 보호합니다.

전략 설계 패턴

  • 구성을 지원합니다.
  • 런타임에 객체의 동작을 변경할 수있는 유연성을 제공합니다.
  • 클라이언트 코드와 솔루션/알고리즘 코드 간의 결합이 적습니다.

템플릿 방법 설계 패턴

  • 구성에 대한 상속을 선호합니다
  • 기본 클래스에서 알고리즘을 정의하십시오. 개별 알고리즘은 아동 클래스에서 사용자 정의 할 수 있습니다.

템플릿 패턴 :

템플릿 메소드는 서브 클래스가 기본 클래스에 정의 된 알고리즘의 기본 구조와 단계를 변경하지 않고 알고리즘의 특정 단계를 재정의하도록하는 것입니다. 템플릿 패턴은 일반적으로 상속을 사용하므로 기본 클래스에서 알고리즘의 일반적인 구현을 제공 할 수 있습니다.이 클래스는 필요한 경우 하위 클래스가 재정의하도록 선택할 수 있습니다.

public abstract class RobotTemplate {
    /* This method can be overridden by a subclass if required */
    public void start() {
        System.out.println("Starting....");
    }

    /* This method can be overridden by a subclass if required */
    public void getParts() {
        System.out.println("Getting parts....");
    }

    /* This method can be overridden by a subclass if required */
    public void assemble() {
        System.out.println("Assembling....");
    }

    /* This method can be overridden by a subclass if required */
    public void test() {
        System.out.println("Testing....");
    }

    /* This method can be overridden by a subclass if required */
    public void stop() {
        System.out.println("Stopping....");
    }

    /*
     * Template algorithm method made up of multiple steps, whose structure and
     * order of steps will not be changed by subclasses.
     */
    public final void go() {
        start();
        getParts();
        assemble();
        test();
        stop();
    }
}


/* Concrete subclass overrides template step methods as required for its use */
public class CookieRobot extends RobotTemplate {
    private String name;

    public CookieRobot(String n) {
        name = n;
    }

    @Override
    public void getParts() {
        System.out.println("Getting a flour and sugar....");
    }

    @Override
    public void assemble() {
        System.out.println("Baking a cookie....");
    }

    @Override
    public void test() {
        System.out.println("Crunching a cookie....");
    }

    public String getName() {
        return name;
    }
}

참고 위의 코드에서 go () 알고리즘 단계는 항상 동일하지만 서브 클래스는 특정 단계를 수행하기 위해 다른 레시피를 정의 할 수 있습니다.

전략 패턴 :

전략 패턴은 클라이언트가 런타임에서 콘크리트 알고리즘 구현을 선택하도록하는 것입니다. 모든 알고리즘은 격리되고 독립적이지만 공통 인터페이스를 구현하며 알고리즘 내에서 특정 단계를 정의한다는 개념은 없습니다.

/**
 * This Strategy interface is implemented by all concrete objects representing an
 * algorithm(strategy), which lets us define a family of algorithms.
 */
public interface Logging {
    void write(String message);
}

/**
 * Concrete strategy class representing a particular algorithm.
 */
public class ConsoleLogging implements Logging {

    @Override
    public void write(String message) {
        System.out.println(message); 
    }

}

/**
 * Concrete strategy class representing a particular algorithm.
 */
public class FileLogging implements Logging {

    private final File toWrite;

    public FileLogging(final File toWrite) {
        this.toWrite = toWrite;
    }

    @Override
    public void write(String message) {
        try {
            final FileWriter fos = new FileWriter(toWrite);
            fos.write(message);
            fos.close();
        } catch (IOException e) {
            System.out.println(e);
        }
    }

}

전체 소스 코드는 내 github를 확인하십시오 저장소.

전략은 추상 클래스로 인터페이스 및 템플릿 메소드로 노출됩니다. 이것은 일반적으로 프레임 워크에 많이 사용됩니다. 예를 들어 Spring Framework의 MessageSource 클래스는 메시지를 해결하기위한 전략 인터페이스입니다. 클라이언트는이 인터페이스의 특정 구현 (전략)을 사용합니다.

그리고 동일한 인터페이스 AbstractMessagesSource의 추상 구현은 메시지를 해결하는 일반적인 구현을 가지고 있으며 resolveCode () 초록 메소드를 노출시켜 하위 클래스가 자신의 방식으로이를 구현할 수 있도록합니다. AbstractMessagesSource는 템플릿 메소드의 예입니다.

http://docs.spring.io/spring/docs/4.1.7.release/javadoc-api/org/springframework/context/support/abstractmessagesource.html

이 설계 패턴의 템플릿 메소드에서, 하나 이상의 알고리즘 단계는 하위 클래스에 의해 상환되어 다른 동작을 허용하면서 가장 중요한 알고리즘이 여전히 추적되도록 보장 할 수 있습니다 (Wiki).

패턴 이름 템플릿 메소드는 그것이 무엇인지를 의미합니다. 메소드 계산 메소드 ()가 있다고 가정 하고이 메소드를 템플릿으로 삼고 싶다고 가정 해 봅시다. 이 방법은 기본 클래스 A 비 가상 메소드에서 선언됩니다. 이 방법이 다음과 같이 보인다 고 가정 해보십시오.

CalculateSomething(){
    int i = 0;
    i = Step1(i);
    i++;
    if (i> 10) i = 5;
    i = Step2(i);
    return i;

} step1 및 step2 메소드 구현은 파생 클래스에서 제공 할 수 있습니다.

전략 패턴에는 기본이 제공 한 구현이 없습니다 (이것이베이스가 실제로 클래스 다이어그램의 인터페이스 인 이유입니다)

전형적인 예는 정렬입니다. 객체의 수를 정렬해야합니다. 적절한 알고리즘 클래스 (병합, 버블, 퀵 등)가 생성되고 전체 알고리즘이 각 클래스에 캡슐화됩니다.

이제 정렬을 템플릿 메소드로 구현할 수 있습니까? 확실히 당신은 할 수 있지만, 당신은 추상화되어 기본 구현에 배치 할 공통점을 많이 찾지 못할 것입니다. 따라서 템플릿 메소드 패턴의 목적을 물리칩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top