앞선에서 다루었던 Data Abstraction입니다.
https://coding-leaf.tistory.com/156
Template Method Pattern
- Superclass의 method로 일반적으로 abstract superclass이며, 수많은 상위 단계의 관점에서 연산의 뼈대(골격)을 정의합니다.
- Abstact keyword를 사용하여 empty implementation을 만듭니다.
- abstract method는 시그니처만 정의되어 있고, body는 비어있는 메소드를 말한다. abstract method를 가지고 있는 class는 abstract class이다. 그리고 abstract class를 추상화하면, 오류가 난다.
- 하위 class에서 abstract의 Template Class의 비어있는 부분(abstract)을 구현합니다.
Purpose of Template Method Pattern
- Operation의 전반적인 구조를 상위 class에서 정의하는 동시에, 하위 class가 특정 단계를 세분화하거나 재정의할 수 있도록 하는 것입니다.
- 기본 class에 알고리즘의 골격을 정의하고 전체 알고리즘의 구조를 변경하지 않고 하위 클래스가 단계를 재정의하도록 합니다.
Example of Template Method Pattern
아래 사이트에서 Template Method Pattern의 예제를 참고했습니다.
https://refactoring.guru/design-patterns/template-method/java/example#example-0
해상 예시에서 Template Method Pattern은 소셜 네트워크로 작업하는 알고리즘으로 정의합니다. 특정 소셜 네트워크와 일하는 하위 class는 소셜 네트워크가 제공하는 API에 따라 이 단계를 구현합니다.
// Demo.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Demo {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
Network network = null;
System.out.print("Input user name: ");
String userName = reader.readLine();
System.out.print("Input password: ");
String password = reader.readLine();
// Enter the message.
System.out.print("Input message: ");
String message = reader.readLine();
System.out.println("\nChoose social network for posting message.\n" +
"1 - Facebook\n" +
"2 - Twitter");
int choice = Integer.parseInt(reader.readLine());
// Create proper network object and send the message.
if (choice == 1) {
network = new Facebook(userName, password);
} else if (choice == 2) {
network = new Twitter(userName, password);
}
network.post(message);
}
}
// --------------------------------------------------------------------------------
// Network.java
public abstract class Network {
String userName;
String password;
Network() {}
/**
* Publish the data to whatever network.
*/
public boolean post(String message) {
// Authenticate before posting. Every network uses a different
// authentication method.
if (logIn(this.userName, this.password)) {
// Send the post data.
boolean result = sendData(message.getBytes());
logOut();
return result;
}
return false;
}
abstract boolean logIn(String userName, String password);
abstract boolean sendData(byte[] data);
abstract void logOut();
}
// --------------------------------------------------------------------------------
// Facebook.java
public class Facebook extends Network {
public Facebook(String userName, String password) {
this.userName = userName;
this.password = password;
}
public boolean logIn(String userName, String password) {
System.out.println("\nChecking user's parameters");
System.out.println("Name: " + this.userName);
System.out.print("Password: ");
for (int i = 0; i < this.password.length(); i++) {
System.out.print("*");
}
simulateNetworkLatency();
System.out.println("\n\nLogIn success on Facebook");
return true;
}
public boolean sendData(byte[] data) {
boolean messagePosted = true;
if (messagePosted) {
System.out.println("Message: '" + new String(data) + "' was posted on Facebook");
return true;
} else {
return false;
}
}
public void logOut() {
System.out.println("User: '" + userName + "' was logged out from Facebook");
}
private void simulateNetworkLatency() {
try {
int i = 0;
System.out.println();
while (i < 10) {
System.out.print(".");
Thread.sleep(500);
i++;
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
// --------------------------------------------------------------------------------
// Twitter.java
public class Twitter extends Network {
public Twitter(String userName, String password) {
this.userName = userName;
this.password = password;
}
public boolean logIn(String userName, String password) {
System.out.println("\nChecking user's parameters");
System.out.println("Name: " + this.userName);
System.out.print("Password: ");
for (int i = 0; i < this.password.length(); i++) {
System.out.print("*");
}
simulateNetworkLatency();
System.out.println("\n\nLogIn success on Twitter");
return true;
}
public boolean sendData(byte[] data) {
boolean messagePosted = true;
if (messagePosted) {
System.out.println("Message: '" + new String(data) + "' was posted on Twitter");
return true;
} else {
return false;
}
}
public void logOut() {
System.out.println("User: '" + userName + "' was logged out from Twitter");
}
private void simulateNetworkLatency() {
try {
int i = 0;
System.out.println();
while (i < 10) {
System.out.print(".");
Thread.sleep(500);
i++;
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
여기까지 잘 따라왔다면 이해하는데 큰 어려움은 없었을 것이다. Network class에서 상속받은 abstract method를 overriding하여 Twitter, Facebook 각기 다른 방법으로 사용하게 됩니다. 이렇게 Template Method Pattern은 같은 역할을 하는 method지만, 다른 class에서 형태만 다르게 구현되는 코드를 작성할 때, 유용하게 사용할 수 있습니다.