您想要設計一個猜數字遊戲,猜數字遊戲的流程大致就是:
顯
示訊息(歡迎)
隨機產生數字
遊戲迴圈
顯示訊息(提示使用者輸入)
取得使用者輸入
比較是否猜中
顯示訊息(輸入正確與否)
隨機產生數字
遊戲迴圈
顯示訊息(提示使用者輸入)
取得使用者輸入
比較是否猜中
顯示訊息(輸入正確與否)
在描述流程輸廓時,並沒有提及如何顯示訊息、沒有提及如何取得使用者輸入等具體的作法,只是歸納出一些共同的流程步驟:
abstract class GuessGame {
protected String welcome;
protected String prompt;
protected String correct;
protected String bigger;
protected String smaller;
void go() {
message(welcome);
int number = (int) (Math.random() * 10);
int guess = 0;
do {
message(prompt);
guess = guess();
if(guess > number) {
message(bigger);
}
else if(guess < number) {
message(smaller);
}
} while(guess != number);
message(correct);
}
protected abstract void message(String message);
protected abstract int guess();
}
如果是個文字模式下的猜數字遊戲,可以將顯示訊息、取得使用者輸入等以文字模式下的具體作法實現出來。例如:
import java.util.Scanner;
class ConsoleGame extends GuessGame {
private Scanner scanner;
ConsoleGame() {
welcome = "歡迎";
prompt = "輸入";
correct = "猜中了";
bigger = "你猜的比較大";
smaller = "你猜的比較小";
scanner = new Scanner(System.in);
}
protected void message(String msg) {
System.out.println(msg);
}
protected int guess() {
return scanner.nextInt();
}
}
public class Main {
public static void main(String[] args) {
GuessGame game = new ConsoleGame();
game.go();
}
}
這是Template Method模式的實例,其在抽象父類別中定義好某個操作的整體流程,而在子類別中才將流程中一些未定的操作實現出來:
如果以Python來實現:
import random
from abc import ABCMeta, abstractmethod
class GuessGame(metaclass=ABCMeta):
@abstractmethod
def message(self, msg):
pass
@abstractmethod
def guess(self):
pass
def go(self):
self.message(self.welcome)
number = int(random.random() * 10)
while True:
guess = self.guess();
if guess > number:
self.message(self.bigger)
elif guess < number:
self.message(self.smaller)
else:
break
self.message(self.correct)
class ConsoleGame(GuessGame):
def __init__(self):
self.welcome = "歡迎"
self.prompt = "輸入數字:"
self.correct = "猜中了"
self.bigger = "你猜的比較大"
self.smaller = "你猜的比較小"
def message(self, msg):
print(msg)
def guess(self):
return int(input(self.prompt))
game = ConsoleGame()
game.go()
在Java 中要撰寫Servlet,會繼承HttpServlet類別,針對GET方法的請求,會重新定義doGet()方法,針對POST方法的請求,會重新定義 doPost()方法....。事實上,這也是Template Method模式的實際例子,因為在HttpServlet處理請求的service()方法中,是這麼定義的:
protected void service(HttpServletRequest req,
HttpServletResponse resp)
throws ServletException, IOException {
String method = req.getMethod(); // 取得請求的方法
if (method.equals(METHOD_GET)) { // HTTP GET
// 略...
doGet(req, resp);
// 略 ...
} else if (method.equals(METHOD_HEAD)) { // HTTP HEAD
// 略 ...
doHead(req, resp);
} else if (method.equals(METHOD_POST)) { // HTTP POST
// 略 ...
doPost(req, resp);
} else if (method.equals(METHOD_PUT)) { // HTTP PUT
// 略 ...
}
當 請求來到時,容器會呼叫Servlet的service()方法,而可以看到,HttpServlet的service()中所定義的,基本上就是判斷 HTTP請求的方式,再分別呼叫doGet()、doPost()等方法,所以若您想針對GET、POST等方法進行處理,才會只需要在繼承 HttpServlet之後,重新定義相對應的doGet()、doPost()方法。
Template Method模式著重的是在父類別實作骨架,而將未實作抽象方法部份留待子類別來實作。先前在說明 Factory Method 模式 前,其實就曾使用過 Template Method模式。
Factory Method 模式將實際要建立的物件推遲至子類中決定,而 Template Method模式則是將框架中抽象的流程部份留待子類來解決。在 Factory Method 模式 的例子中,從物件 建立的角度來看,createDocument()是Factory Method,而從流程框架的角度來看,createDocument()則是 Template Method模式的一個方法實作。