Template Method Pattern(탬플릿 메소드 패턴)
Template Method Pattern(탬플릿 메소드 패턴)이란 알고리즘을 절차적 단위로 구분하여 단계별로 메소드화 하고 이를 상속하는 자식 클래스가 필요한 형태로 오버라이드해서 사용하는 패턴을 의미한다.
탬플릿 메소드를 사용하는 이유는
1. 반복되는 작업이 진행될 때 효율적으로 작업이 가능
2. 기능별로 잘 나누어져 있기 때문에 유지, 보수가 편리
이렇게 크게 두 가지로 볼 수 있는 것 같다. 간단히 말해서 일정한 프로세스를 가진 요구사항을 프로그래밍으로 구현한다면 차후 있을 수도 있는 유지, 보수사항을 감안하여 Template Method Pattern(탬플릿 메소드 패턴)을 활용해서 짜는 것이 좋겠다.
abstract class AbstConnectionHelper {
String Id, Password, UserAuthority;
public void SetId(String id) {
this.Id = id;
}
public void SetPassword(String password) {
this.Password = password;
}
public void SetUserAutority(String userauthority) {
this.UserAuthority = userauthority;
}
protected abstract String Security(String id, String password);
protected abstract void Authentication(String id, String password);
protected abstract void Authorization(String userAuthority);
protected abstract void Connection();
public void DoConnection() {
Security(Id, Password);
Authentication(Id, Password);
Authorization(UserAuthority);
Connection();
};
}
public class ConcConnectionHelper extends AbstConnectionHelper {
String id = "aaa"; // 서버에 저장된 ID
String password = "bbb";// 서버에 저장된 Password
protected String Security(String Id, String Password) {
System.out.println("입력받은 정보를 보안 처리 합니다");
return "Success";
}
protected void Authentication(String Id, String Password) {
if ((Id.equals(id)) && (Password.equals(password))) {
System.out.println("아이디와 비밀번호가 일치합니다");
} else {
System.out.println("아이디와 비밀번호가 일치하지 않습니다");
System.exit(0);
}
}
protected void Authorization(String UserAuthority) {
System.out.println(UserAuthority + "User환경을 적용합니다");
}
protected void Connection() {
System.out.println("서버에 연결합니다");
}
}
public class Main {
public static void main(String[] args) {
AbstConnectionHelper Connector = new ConcConnectionHelper();
Scanner sc = new Scanner(System.in);
System.out.print("ID를 입력하세요 : ");
String Id = sc.next();
System.out.print("Password를 입력하세요 : ");
String Password = sc.next();
System.out.print("회원 종류를 입력하세요(유료, 무료, PC방) : ");
String UserAuthority = sc.next();
Connector.SetId(Id);
Connector.SetPassword(Password);
Connector.SetUserAutority(UserAuthority);
Connector.DoConnection();
}
}
괜히 내가 이것저것 붙이다가 시간만 더 갔다. 실력 향상에 도움이 되긴 하지만 그냥 다음부터는 배운 패턴에 맞는 기능만 익히는 것으로 해야겠다. 그래서 내가 밑에 정말 간단한 예시로 개념만 다시 리뷰해 보았다. 한 블로거의 포스팅을 참조했다. (http://itcrowd2016.tistory.com/22) 훨씬 개념 이해에 도움이 되고 시간도 단축되었다. 나는 복습을 위한 공부 기록을 하는 것이 목적이기 때문에 이런 방법이 훨씬 좋겠다는 생각이 들었고 앞으로도 어떤 패턴을 배우고 기록을 하든지 왠만하면 이런 방식으로 sysout만 써서 간편하게 기록할 것이다.
-------------------------------------------------------------------------------------------------------------
핵심은 간단하다. 개념은 당연히 위와 마찬가지이다. 햄버거를 만든다는 행위(알고리즘)를 세분화 하여 정리(절차별로 메소드화)하고 가변적 절차는 선언만 하고 구현은 하지 않는다. 겹치고 바뀌지 않는 절차는 구현까지 한다. 그리고 햄버거를 만드는 행위를 하나의 행위로 묶어서 나누었던 메소스들을 담에 하나의 메소드로 만든다.
여기서 왜 Template Method Pattern(탬플릿 메소드 패턴)에서 인터페이스를 쓰지 않고 추상 클래스를 사용하는지 알아차릴 수 있다. 선언만 하고 넘어갈 것이 아니라 구현도 해야하거나 하고 싶은 메소드가 섞여 있을 수 있기 때문이다. 인터페이스에서는 오직 선언만 가능하고 추상 클래스에서는 선언과 구현이 동시에(섞어서) 가능하다.
각 클래스들은 각자의 특성에 맞게 바꿔야하는 행위들을 Override한다. 아래 예시에서는 빵 종류, 치즈 종류, 고기 종류가 달라져야 했으므로 각각 Override 하였다.
abstract class MakeHambg {
protected abstract void Bread();
protected void Vegetable() {
System.out.println("야채를 놓는다.");
}
protected void Sauce() {
System.out.println("케첩을 뿌린다.");
}
protected abstract void Meat();
protected abstract void Cheeze();
public void Hamburger() {
Bread();
Vegetable();
Sauce();
Meat();
Sauce();
Cheeze();
Bread();
}
}
public class BigMac extends MakeHambg {
protected void Bread() {
System.out.println("호밀빵을 놓는다");
}
protected void Meat() {
System.out.println("빅맥용 고기를 놓는다");
}
protected void Cheeze() {
System.out.println("일반 치즈를 놓는다");
}
}
public class Cheezeburger extends MakeHambg {
protected void Bread() {
System.out.println("일반 빵을 놓는다");
}
protected void Meat() {
System.out.println("일반 고기를 놓는다");
}
protected void Cheeze() {
System.out.println("엄청난 치즈를 놓는다");
}
}
public class TestMain {
public static void main(String[] args) {
MakeHambg bm = new BigMac();
MakeHambg cb = new Cheezeburger();
System.out.println("<<< 호밀빵 빅맥 >>>");
bm.Hamburger();
System.out.println("========== 구 분 선 ==========");
System.out.println("<<< 치즈버거 >>>");
cb.Hamburger();
}
}
똑같은 Hamburger()를 실행하였는 Override를 한 빵, 고기, 치즈만 내용이 바뀌었다. 만약, 다른 햄버거를 만들어야 하는 추가 사항이 생기면 필요한 부분만 Override해서 그대로 Hamburger()를 사용하면 된다. 이렇게 Hamburger()처럼 절차가 바뀌지 않고 같은 틀을 유지하되 메소드 세부 내용만 변경하면 된다라고 할 때 Template Method Pattern(탬플릿 메소드 패턴)은 매우 유용한 것 같다.