디자인 패턴 (9) - 템플릿 메소드 패턴

템플릿 (템플릿) 패턴의 방법 에있어서의 알고리즘의 골격을 정의하는 서브 클래스 일부 단계는 지연. 알고리즘의 구조를 변경하지 않고 이러한 서브 공판에있어서, 알고리즘의 단계 중 일부가 재정의된다. 이 모드는 알고리즘 템플릿을 만드는 데 사용되는 템플릿은 방법이다. 구체적으로는, 알고리즘의 방법은 일련의 단계로 정의하고, 모든 단계는 추상적 일 수 있고, 그 서브 클래스 구현을 담당한다. 이 알고리즘은 부분 서브 달성 제공하면서도 구조가 변경되지 않도록 할 수있다.

직접 예를 아래 설명한다.

커피 숍에서 두 커피 음료와 차가, 자신의 양조 방법은 다음과 같습니다 :

커피

  1. 물을 끓여
  2. 커피는 끓는 물에 양조
  3. 그녀는 컵에 커피를 부어
  4. 설탕과 우유

  1. 물을 끓여
  2. 끓는 물에 침수와 차
  3. 차 컵에 부어
  4. 레몬

우리는 자신의 1 단계와 3을 볼 수 있습니다, 사실, 같은, 2, 4 다르지만 다소 유사하다. 우리는 추상 클래스를 설계하는, 한 가지 공통점을 추출 할 수 있습니다 :

public abstract class CaffeineBeverage {
  
	final void prepareRecipe() {
		boilWater();
		brew();
		pourInCup();
		addCondiments();
	}
 
	abstract void brew();
  
	abstract void addCondiments();
 
	void boilWater() {
		System.out.println("Boiling water");
	}
  
	void pourInCup() {
		System.out.println("Pouring into cup");
	}
}

그리고 상속을 통해, 각각 커피와 차를 실현

public class Coffee extends CaffeineBeverage {
	public void brew() {
		System.out.println("Dripping Coffee through filter");
	}
	public void addCondiments() {
		System.out.println("Adding Sugar and Milk");
	}
}
public class Tea extends CaffeineBeverage {
	public void brew() {
		System.out.println("Steeping the tea");
	}
	public void addCondiments() {
		System.out.println("Adding Lemon");
	}
}

"후크"

상기는의에 대해 말해,의 깊은 다시 조금 발굴 할 기본 응용 프로그램 템플릿 메소드 패턴 "훅" .

후크는 방법을 다시 추상 클래스를 선언,하지만 비우거나 디폴트의 구현입니다. 후크는 서브 클래스를 허용하는 알고리즘의 다른 지점에 연결 할 수있는 능력을 가지고 있습니다. 자신의 서브 클래스에 연결되지합니다.

그럼 그냥 예를 들어, 후크, 우리는 여부를 재정의 방법을 결정할 수 있습니다. 당신은 자신의 방법을 제공하지 않는 경우, 추상 클래스는 기본 구현을 제공합니다.

public abstract class CaffeineBeverageWithHook {
 
	void prepareRecipe() {
		boilWater();
		brew();
		pourInCup();
		if (customerWantsCondiments()) {
			addCondiments();
		}
	}
 
	abstract void brew();
 
	abstract void addCondiments();
 
	void boilWater() {
		System.out.println("Boiling water");
	}
 
	void pourInCup() {
		System.out.println("Pouring into cup");
	}
 
	boolean customerWantsCondiments() {
		return true;
	}
}

후크를 사용하기 위해, 우리는 하위 클래스에서 재정의해야합니다. 그럼 그냥 그 예를 들어, 우리는 알고리즘의 일부, 그것은 더 명확 포인트가 추가 향신료를 마시는 지 여부에 넣어 여부 카페인 음료 후크 컨트롤을 사용할 수 있습니다.

import java.io.*;

public class CoffeeWithHook extends CaffeineBeverageWithHook {
 
	public void brew() {
		System.out.println("Dripping Coffee through filter");
	}
 
	public void addCondiments() {
		System.out.println("Adding Sugar and Milk");
	}
 
	public boolean customerWantsCondiments() {

		String answer = getUserInput();

		if (answer.toLowerCase().startsWith("y")) {
			return true;
		} else {
			return false;
		}
	}
 
	private String getUserInput() {
		String answer = null;

		System.out.print("Would you like milk and sugar with your coffee (y/n)? ");

		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		try {
			answer = in.readLine();
		} catch (IOException ioe) {
			System.err.println("IO error trying to read your answer");
		}
		if (answer == null) {
			return "no";
		}
		return answer;
	}
}
import java.io.*;

public class TeaWithHook extends CaffeineBeverageWithHook {
 
	public void brew() {
		System.out.println("Steeping the tea");
	}
 
	public void addCondiments() {
		System.out.println("Adding Lemon");
	}
 
	public boolean customerWantsCondiments() {

		String answer = getUserInput();

		if (answer.toLowerCase().startsWith("y")) {
			return true;
		} else {
			return false;
		}
	}
 
	private String getUserInput() {
		// get the user's response
		String answer = null;

		System.out.print("Would you like lemon with your tea (y/n)? ");

		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		try {
			answer = in.readLine();
		} catch (IOException ioe) {
			System.err.println("IO error trying to read your answer");
		}
		if (answer == null) {
			return "no";
		}
		return answer;
	}
}

테스트 코드

public class BeverageTestDrive {
	public static void main(String[] args) {
 
		Tea tea = new Tea();
		Coffee coffee = new Coffee();
 
		System.out.println("\nMaking tea...");
		tea.prepareRecipe();
 
		System.out.println("\nMaking coffee...");
		coffee.prepareRecipe();

 
		TeaWithHook teaHook = new TeaWithHook();
		CoffeeWithHook coffeeHook = new CoffeeWithHook();
 
		System.out.println("\nMaking tea...");
		teaHook.prepareRecipe();
 
		System.out.println("\nMaking coffee...");
		coffeeHook.prepareRecipe();
	}
}

운영 결과

이 예에서, 후크 영향은 매우 멋진 추상 클래스를, 흐름 알고리즘, 제어 조건으로 역할을 할 수 있습니다. 우리는 후크 여러 용도를 결론 내릴 수있다

  • 옵션 부분에 서브 클래스 알고리즘을하자, 또는 후크 연결할 수 있습니다 서브 클래스의 서브 클래스의 실현을위한 중요하지 않은 경우에이 옵션을 무시합니다.
  • 하자 서브 클래스 (또는 발생) 단계 임박한 템플릿 방법의 일부에 응답 할 기회를 가질 수있다. 예를 들어, 호출 justReOrderedList()후크 방법 서브 재구성 내부에서 특정 작업을 수행 할 수 있도록 (예를 들어, 데이터를 화면에 재현).
  • 후크는 그 서브 클래스 추상 클래스가 어떤 결정을 내릴 수 있습니다.

디자인 원칙

템플릿 접근 방식으로 알려진 새로운 디자인 원칙을 반영 할리우드 원리 : 음주, (전화)로 전화하지 우리는 (전화)를 호출합니다 .

할리우드는 우리에게 방지하는 원리를 제공 할 수 있습니다 "의존성 손상" 접근 방식을. 고레벨 성분이 기본 성분에 의존하고, 로우 레벨의 컴포넌트와 고레벨 성분 의존하면, 이번에는 성분 측 저레벨 성분 종속 종속 손상이 발생 조립체 하이 측 구성 요소에 의존한다.

할리우드의 원칙에 따라, 우리는 낮은 수준의 구성 요소가 시스템에 스스로를 후크 할 수 있지만, 높은 수준의 조립 언제, 어떻게 이러한 낮은 수준의 구성 요소를 사용하기로 결정합니다. 즉. 접근의 치료 낮은 수준의 구성 요소에 대한 높은 수준의 구성 요소는 "음주로 전화, 우리가 전화 할게 없다"입니다.

또한 도입이 시리즈의 이전 기사에서 템플릿 메소드 패턴, 관찰자 ​​패턴 및 공장 방법 패턴뿐만 아니라 할리우드의 원칙을 반영한다.

게시 된 295 개 원래 기사 · 원 찬양 37 ·은 30000 +를 볼

추천

출처blog.csdn.net/tianshan2010/article/details/104714020