본문으로 건너뛰기

디자인 패턴 중 템플릿 메서드 패턴 (Template Method Pattern)

무료2015-03-07#Design_Pattern#模版方法模式#Template Method Pattern

템플릿 메서드 패턴은 알고리즘의 골격 (프로세스) 을 캡슐화하는 데 사용되며, 특정 단계는 서브클래스가 구현합니다. 또한 또 다른 패턴으로 스트래티지 패턴이 있으며, 둘 다 알고리즘을 캡슐화하는 데 사용되지만 중점점이 다릅니다. 본고에서 자세히 논의합니다.

no_mkd

一。템플릿 메서드 패턴이란 무엇인가?

먼저, 템플릿 메서드 패턴은 알고리즘의 골격을 캡슐화하는 데 사용됩니다. 즉 알고리즘 프로세스입니다

템플릿이라고 불리는 만큼, 당연히 확장 클래스가 이 템플릿을 적용할 수 있도록 허용하며, 변화에 대응하기 위해 확장 클래스가 일부 변경을 할 수 있도록 허용해야 합니다

사실 그通り로, 템플릿 메서드 패턴은 알고리즘 프로세스를 캡슐화하지만, 특정 단계의 세부 사항 구현은 서브클래스가 담당합니다

二。예를 들다

프랜차이즈를 허용하는 작장면 가게를 연다고 가정해 봅시다. 우리에게는 독점 비법의 소스 레시피와 독특한 제조 공예��� 있으며, 맛은 이곳뿐입니다. 지구상의 대부분의 사람들이 매일 우리의 작장면을 먹으므로, 많은 프랜차이즈 가맹점이 있습니다

수익을 내기 위해, 물론 제조 공예와 소스 레시피를 공개할 수는 없지만, 프랜차이즈 가맹점의 경영 지역 차이로 인해 제조 세부 사항에 차이가 있습니다. 예를 들어 베이징 사람들은 얇고 딱딱한 면을 좋아하고, 섬서 사람들은 넓고 부드러운 면을 좋아합니다. 레시피를 보호하기 위해 베이징 프랜차이즈 가맹점에 계속 넓은 면을 팔게 할 수도 없습니다

따라서 제조 공예와 비법 레시피를 보호하여 아무도 수정할 수 없도록 하면서도, 면의 제조와 조리 방법은 공개하여 프랜차이즈 가맹점이 수정할 수 있도록 해야 합니다. 그렇다면, 어떻게 이러한 요구를 실현할 수 있을까요?

맞습니다, 템플릿 메서드가 바로 이를 위해 존재합니다

먼저, 템플릿 클래스를 정의하여 보호해야 할 것은 보호하고 공개해야 할 것은 공개합니다:

package TemplateMethodPattern;

/**

  • @author ayqy

  • 작장면 템플릿 클래스 정의 */ public abstract class Noodles { public void cook(){ //면 제조 makeNoodles(); //소스 제조 makeSauce(); //면 조리 boilNoodles(); //소스 추가 addSauce(); }

    /**

    • 비법 소스 보호 */ private void makeSauce(){ System.out.println("독점 비법 소스 완성"); }

    /**

    • 첨가량 보호 */ private void addSauce(){ System.out.println("적량의 비법 소스 추가"); }

    public abstract void makeNoodles(); public abstract void boilNoodles(); }

템플릿을 정의하면, 90% 의 작업이 완료된 것입니다. 이제 구체 클래스를 구현합니다

베이징 작장면:

package TemplateMethodPattern;

/**

  • @author ayqy

  • 베이징 작장면 구체 클래스 구현 */ public class BJNoodles extends Noodles{

    @Override public void makeNoodles() { System.out.println("베이징 특색의 수타면 완성"); }

    @Override public void boilNoodles() { System.out.println("베이징 특색 면 조리법으로 면 조리"); } }

섬서 작장면:

package TemplateMethodPattern;

/**

  • @author ayqy

  • 섬서 작장면 구체 클래스 구현 */ public class SXNoodles extends Noodles{

    @Override public void makeNoodles() { System.out.println("섬서 특색의 수타면 완성"); }

    @Override public void boilNoodles() { System.out.println("섬서 특색 면 조리법으로 면 조리"); } }

이러한 구체 클래스가 있으면, 지역별로 프랜차이즈 가맹점에 배분하면 됩니다

三。효과 예시

먼저 테스트 클래스를 구현합니다:

package TemplateMethodPattern;

/**

  • @author ayqy

  • 테스트 클래스 구현 */ public class Test { public static void main(String[] args){ //베이징 작장면 객체 생성 Noodles bjnoodles = new BJNoodles(); //섬서 작장면 객체 생성 Noodles sxnoodles = new SXNoodles();

     System.out.println("베이징 작장면 제조 공예:");
     bjnoodles.cook();//베이징 작장면 1 인분 만들기
     System.out.println("\n섬서 작장면 제조 공예:");
     sxnoodles.cook();//섬서 작장면 1 인분 만들기
    

    } }

실행 결과:

四。조금 더 생각하기

위의 예에서, 우리는 알고리즘 골격의 캡슐화를 쉽게 실현했고, 확장 클래스가 특정 단계의 세부 사항을 커스터마이즈할 수 있도록 했습니다. 매우 쉽고 완벽해 보일 수 있습니다

그렇다면, 요구를 변경해 봅시다:

최근 녹색 건강한 생활이 권장되어, 모두 채소를 먹는 것을 좋아합니다. 우리의 전통적인 작장면도 시대에 맞춰 발전하여, 완성 후 채소를 추가해야 합니다. 하지만 문제는 일부 지역에서는 채소 추가를 좋아하지 않는다는 것입니다. 그들은 노포 작장면의 풍미에 익숙하며, 채소를坚决로 거부합니다. 따라서 제조 공예를 간단히 변경하여 채소를 추가하는 공정을 추가할 수 없습니다. 템플릿에서선택 가능한 조작을 정의할 수 있다면 더할 나위 없이 좋을 것입니다. 프랜차이즈 가맹점이 채소를 추가할지 말지를 스스로 선택할 수 있도록

이에, 이전 템플릿을 조금 수정해야 합니다:

package TemplateMethodPattern;

/**

  • @author ayqy

  • 작장면 템플릿 클래스 정의 */ public abstract class Noodles { private boolean wantVegetables = false;//채소 필요 여부

    public void setWantVegetables(boolean wantVegetables) { this.wantVegetables = wantVegetables; }

    public void cook(){ //면 제조 makeNoodles(); //소스 제조 makeSauce(); //면 조리 boilNoodles();

     //채소 추가 여부
     if(wantVegetables)
     	addVegetables();
     
     //소스 추가
     addSauce();
    

    }

    /**

    • 비법 소스 보호 */ private void makeSauce(){ System.out.println("독점 비법 소스 완성"); }

    /**

    • 첨가량 보호 */ private void addSauce(){ System.out.println("적량의 비법 소스 추가"); }

    /**

    • 제철 채소 추가 */ public void addVegetables(){ //빈 구현 }

    public abstract void makeNoodles(); public abstract void boilNoodles(); }

주의, 선택 가능한 조작을 추가하기 위해, 다음과 같은 일을 했습니다:

  1. 플래그 변수 정의 (선택/비선택)
  2. 플래그 변수의 setter 제공, 확장 클래스가 선택할 수 있도록
  3. 알고리즘 골격 수정, 새로운 선택 가능한 단계 추가
  4. 새로운 단계에 빈 구현 제공 (주의, 이 단계는 매우 중요합니다. 빈 구현을 제공하고 추상 메서드를 정의하지 않음으로써, 기존 확장 클래스의 수정을 피합니다. 이는 템플릿 메서드 패턴의 용어에서Hook 후크라고 불립니다)

五。템플릿 메서드 패턴과 스트래티지 패턴

이 두 패턴은 모두 알고리즘을 캡슐화하는 데 사용됩니다. 비교해 봅시다:

 스트래티지 패턴템플릿 메서드 패턴
개념알고리즘 단계를 캡슐화하고, 서브클래스가 기존 스트래티지 (단계 세부 사항) 를 선택할 수 있도록알고리즘 골격 (프로세스) 을 캡슐화하고, 서브클래스가 특정 세부 사항을 구현하도록
구현 방식컴포지션으로 구현상속으로 구현
목표알고리즘 단계의 선택 실현알고리즘의 프로세스 제어 실현
亮点실행 시에 단계 (스트래티지) 를 동적으로 변경 가능실행 시에 알고리즘 프로세스를 동적으로 변경 가능 (hook 으로 구현)
구체 단계변화하기 쉬운 동류의 알고리즘 세부 사항 (단계) 을 찾아, 알고리즘 패밀리 (인터페이스) 를 정의하여 캡슐화알고리즘 골격을 추상화하여 베이스 클래스 (템플릿 클래스) 에 캡슐화
요약단계 캡슐화프로세스 캡슐화

예를 들겠습니다:

현재 프로세스가 A->B->C->D 인 알고리즘이 있다고 가정합니다. C 단계의 구체 구현에는 c1,c2,c3 의 세 가지 다른 방법이 있습니다

스트래티지 패턴:

  1. 행동 인터페이스 C 를 정의하고, execute 메서드 정의
  2. 구체 클래스 c1,c2,c3 를 인터페이스 C 에서 확장 (c1,c2,c3 의 세 가지 행동을 호출자가 선택 가능)
  3. 베이스 클래스에 속성 추가, 타입을 인터페이스 C 로 하고, setter 제공
  4. 베이스 클래스에서 확장한 구체 클래스는 setter 를 호출하여 동적으로 행동 변경

템플릿 메서드 패턴:

  1. 베이스 클래스 (템플릿 클래스) 정의, 베이스 클래스에서 알고리즘 프로세스 정의 (프로세스 캡슐화)
  2. 베이스 클래스에서 C 단계를 추상 메서드로 정의
  3. 베이스 클래스에서 확장한 구체 클래스는 자체 구현 제공 (c1,c2,c3 또는 기타)

댓글

아직 댓글이 없습니다

댓글 작성