mojo's Blog

Template Method Pattern 본문

Design Patterns

Template Method Pattern

_mojo_ 2024. 6. 6. 14:46

Template Method Pattern

 

목적: 알고리즘의 프레임워크를 식별하여 클래스를 구현하여 실제 동작을 정의할 수 있도록 함

사용 시기

- 알고리즘의 단일 추상적 구현이 필요함

- 하위 클래스 간에 공통된 동작은 공통 클래스에 국한되어야 함

- 부모 클래스는 하위 클래스의 동작을 균일하게 호출할 수 있어야 함

- 대부분 또는 모든 하위 클래스는 동작을 구현해야 함

 

두 클래스를 살펴보도록 한다.

 

※ Class Philosopher

public class Philosopher {
	void prepareEat() {
		think();
		leftHandup();
		rightHandup();
		eat();
	}
	public void think() { // impl think }
	public void leftHandup() { // impl leftHand }
	public void rightHandup() { // impl rightHand }
	public void eat() { // impl eat }
}

 

철학자의 먹는 순서

(1) 생각을 함

(2) 왼쪽 손을 듬

(3) 오른쪽 손을 듬

(4) 먹음

 

※ Class Scientist

public class Scientist {
	void prepareEat() {
		think();
        rightHandup();
		leftHandup();
		eat();
	}
	public void think() { // impl think }
	public void leftHandup() { // impl leftHand }
	public void rightHandup() { // impl rightHand }
	public void eat() { // impl eat }
}

 

과학자의 먹는 순서

(1) 생각을 함

(2) 오른쪽 손을 듬

(3) 왼쪽 손을 듬

(4) 먹음

 

철학자와 과학자는 손을 드는 순서가 변경되었다. (그 외 과정은 동일)

두 코드는 클래스 간에 중복된다.

클래스를 더 추가할 수록 먹는 방식이 달라져 중복이 더 발생할 수 있으며,

알고리즘 및 구현에 대한 지식은 클래스에 분산되어 진다.

 

※ Abstracting prepareEat()

public abstract class Person {
	final void prepareEat() {
		think();
		handsUp();
		eat();
	}
   	abstract void handsUp();
    
	public void think() { // impl think }
	public void eat() { // impl eat }
}

public class Philosopher extends Person {
	public void handsUp() {
    	// impl leftHand
        // impl rightHand
    }
}

public class Scientist extends Person {
	public void handsUp() {
    	// impl rightHand
        // impl leftHand
    }
}

 

사람마다 손드는 방식이 다르며 그 외 생각, 먹기 순서가 동일하다고 하다면 위와 같이 추상 클래스를 만들 수 있다.

추상 메서드 handsUp 를 둬서 사람마다 handsUp 를 오버라이딩한다면 중복 코드를 방지할 수 있다.

prepareEat() 메서드는 템플릿 메서드라고 불린다.

 

※ More General Approach

변경사항

- 두 하위 클래스 모두 일반 알고리즘을 상속함 (생각 -> 손들기 -> 먹기)

- 알고리즘의 일부 방법은 모든 하위 클래스에 대해 동일한 작업을 수행하는 구체적인 방법임 (생각, 먹기)

- 알고리즘의 다른 방법은 추상적이며, 클래스 별 작업을 수행하는 방법임 (손들기)

 

장점

- 단일 클래스는 알고리즘, 즉 Person의 생각, 먹기 알고리즘을 보호하고 제어함

- 슈퍼 클래스는 방법의 재사용을 용이하게 함

- 코드 변경은 한 곳에서만 발생함 (손 들기)

- 철학자, 과학자 외에 다른 사람들을 쉽게 추가할 수 있음 (손 들기만 변경한다면)

 

※ Template Method Pattern

- prepareEat() 는 템플릿 메서드 패턴을 구현함

- 알고리즘, 즉 먹는 것을 준비하기 위한 템플릿 역할을 함

- 템플릿에서 각 단계는 메서드로 표시되어짐 (생각, 손들기, 먹기 등)

- 일부 방법은 슈퍼 클래스에서 구현되며, 다른 방법은 하위 클래스에서 구현되며 추상적으로 선언됨

 

※ Hook Method

Hook는 추상 클래스에서 선언되지만 비어있거나 기본 구현만 제공되는 메서드이다.

하위 클래스가 원하는 경우 다양한 지점에서 알고리즘을 "Hook" 할 수 있는 기능을 제공한다.

또한 하위 클래스는 후크를 무시할 수 있다.

 

public abstract class Person {
	final void prepareEat() {
		think();
		if (personWantsHandsUp()) handsUp();
		eat();
	}
   	abstract void handsUp();
    
	public void think() { // impl think }
	public void eat() { // impl eat }
    boolean personWantsHandsUp() {
    	return true;
    }
}


public class Philosopher extends Person {
	public void handsUp() {
    	// impl leftHand
        // impl rightHand
    }
    public boolean personWantsHandsUp() {
    	String answer = getUserInput();
       	return answer.toLowerCase().startsWith("y");
    }
}

 

위와 같이 철학자가 y 를 말하면 왼손, 오른손을 들고 y 를 말하지 않으면 손을 들지 않을 수 있다.

 

※ Template Method Pattern vs. Strategy Pattern

Template Method는 상속을 이용하여 알고리즘의 일부를 변경한다.

Strategy는 delegation을 사용하여 전체 알고리즘을 변경한다.

 

'Design Patterns' 카테고리의 다른 글

Mediator Pattern  (0) 2024.06.06
State Pattern  (0) 2024.06.06
Observer Pattern  (1) 2024.06.06
Strategy Pattern  (0) 2024.06.06
GRASP  (1) 2024.05.15
Comments