Template Method Pattern 이란?
전체적인 알고리즘은 상위 클래스에서 구현하면 서 다른 부분은 하위 클래스에서 구현할 수 있도록 하는 디자인 패턴
전체적으로는 동일하면서 부분적으로는 다른 구문으로 구성된 메서드의 코드 중복을 최소화할 때 유용
- AbstractClass : 템플릿 메서드를 정의하는 클래스. 하위 클래스에 공통 알고리즘을 정의하고 하위 클래스에서 구현될 기능을 primitive 메서드 또는 hook 메서드로 정의하는 클래스
- ConcreteClass : 물려받은 primitive 메서드나 hook 메서드를 구현하는 클래스. 상위 클래스에 구현된 템플릿 메서드의 일반적인 알고리즘에서 하위 클래스에 적합하게 primitive 메서드나 hook 메서드를 오버라이드 하는 클래스)
* 템플릿 메서드 : 동일한 기능을 구현하면서 각 하위 클래스에서 구체적으로 정의할 필요가 있는 부분
* primitive 메서드(= hook 메서드) : 템플릿 메서드에서 호출되면서 하위 클래스에서 오버라이드될 필요가 있는 부분
Templete 메서드 구현
교재 예시 : 엘레베이터 제어 시스템의 모터 구동 기능
- HyundaiMotor 클래스는 move 메서드 실행 시 door클래스 상태 확인(열려있으면 닫기)
- 엘리베이터가 이미 이동중일 경우 모터 구동 필요 없음
- move method(구동 메서드) : 모터 상태 조회 → 동작중이면 종료, 아니라면 문 상태 조회 → 모터 구동
public enum DoorStatus {CLOSED, OPENED}
public enum MotorStatus {MOVING, STOPPED}
public class Door {
private DoorStatus doorStatus;
public Door(){
doorStatus = DoorStatus.CLOSED;
}
public DoorStatus getDoorStatus(){
return doorStatus;
}
public void close(){
doorStatus = DoorStatus.CLOSED;
}
public void open(){
doorStatus = DoorStatus.OPENED;
}
}
public class HyundaiMotor {
pirvate Door door;
private MotorStatus motorStatus;
public HyundaiMotor(Door door){
this.door = doorl
motorStatus = MotorStatus.STOPPED; // 초기에는 멈춘 상태
}
private void moveHyundaiMotor(Direction direction){
//Hyundai motor 구동시킴
}
public MotorStatus getMotorStatus(){
return motorStatus;
}
private void setMotorStatus(MotorStatus motorStatus){
this.motorStatus = motorStatus;
}
public void move(Direction direction){
MotorStatus motorStatus = getMotorStatus();
if (motorStatus == MotorStatus.MOVING) // 이동중이면 아무작업 하지 않음
return;
DoorStatus doorStatus = door.getDoorStatus();
if (doorStatus == DoorStatus.OPENED)
door.close();
moveHyndaiMotor(direction); // 모터를 주어진 방향으로 이동
setMotorStatus(MotorStatus.MOVING); // 모터 상태를 이동중으로 변경
}
}
public class Client {
public static void main(String args[]){
Door door = new Door();
HyndaiMotor hyndaiMotor = new HyndaiMotor(door);
hyundaiMotor.move(Direction.UP);
}
}
문제점
문제 상황 : 다른 회사의 모터를 제어해야 하는 경우
- 모터 구동에 있어 다른 회사의 제품이기 때문에 완전히 동일하지는 않지만, 많은 부분 코드의 중복이 발생하는 문제
- 상속을 통해 해결(중복되는 부분을 상위클래스로 옮김 + 다르게 동작하는 부분은 각각의 클래스가 구현하게 함) → 각각의 클래스가 구현한 함수(move)에 대해서도 여전히 중복되는 부분이 많음
문제 해결
중복되는 부분만 메소드로 상위 클래스에 두고, 다르게 동작하는 부분은 추상 메소드로 두어 구현하게 함
public abstract class Motor {
private Door door;
private MotorStatus motorStatus;
public Motor(Door door){
this.door = door;
motorStatus = MotorStatus.STOPPED;
}
public MotorStatus getMotorStatus(){
return motorStatus;
}
private void setMotorStatus(MotorStatus motorStatus){
this.motorStatus = motorStatus;
}
// LGMotor와 HyundaiMotor의 move 메서드에서 공통되는 부분만 가짐
public void move(Direction direction){
MotorStatus motorStatus = getMotorStatus();
if (motorStatus == MotorStatus.MOVING)
return;
DoorStatus doorStatus = door.getDoorStatus();
if (doorStatus == DoorStatus.OPENED)
door.close();
moveMotor(direction);
setMotorStatus(MotorStatus.MOVING);
}
protected abstract void moveMotor(Direction direction);
}
public class HyndaiMotor extends Motor {
public HyundaiMotor(Door door){
super(door);
}
protected void moveMotor(Direction direction){
//HyundaiMotor 구동시킴
}
}
public class LGMotor extends Motor {
public LGMotor(Door door){
super(door);
}
protected void moveMotor(Direction direction){
//LGMotor 구동시킴
}
}
'Design pattern' 카테고리의 다른 글
[Design Pattern] Abstract Factory Pattern (0) | 2022.08.22 |
---|---|
[Desigan Pattern] Factory Method Pattern (0) | 2022.08.17 |
[Design Pattern] Decorator Pattern (0) | 2022.08.10 |
[Design Pattern] Observer Pattern (0) | 2022.08.04 |
[Design Pattern] Command Pattern (0) | 2022.08.01 |