在抽象類中定義演算法骨架 (模板方法),將某些步驟延遲到子類實現。子類可在不改變演算法結構情況下,重新定義特定步驟。
abstract class AbstractSort {
// 模板方法:final 防止子類破壞流程
public final void showSortResult(int[] arr) {
sort(arr); // 抽象步驟:由子類實現
printResult(arr); // 具體步驟:統一列印
}
protected abstract void sort(int[] arr); // 必須實現
// 鉤子方法:預設實現,子類可選覆寫
protected boolean isAscending() { return true; }
private void printResult(int[] arr) {
System.out.print("排序結果: ");
for (int v : arr) System.out.printf("%3d", v);
System.out.println();
}
}
// 子類:選擇排序
class SelectionSort extends AbstractSort {
protected void sort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int idx = i;
for (int j = i + 1; j < arr.length; j++)
if (arr[j] < arr[idx]) idx = j;
int tmp = arr[i]; arr[i] = arr[idx]; arr[idx] = tmp;
}
}
}
// 子類:降序排序 (覆寫鉤子方法)
class DescendingSort extends SelectionSort {
protected boolean isAscending() { return false; }
// 若需改變列印邏輯,可覆寫 printResult (但它是 private,需改 protected)
}
// 客戶端
public class TemplateMethodDemo {
public static void main(String[] args) {
int[] data = {10, 32, 1, 9, 5, 7, 12, 0, 4, 3};
new SelectionSort().showSortResult(data); // 升序
new DescendingSort().showSortResult(data); // 降序 (需配合打印邏輯)
}
}
| 類型 | 定義者 | 子類可否覆寫 | 用途 |
|---|---|---|---|
| 抽象方法 | 抽象類 | 必須實現 | 核心變化點 |
| 模板方法 | 抽象類 | 不可 (final) | 固定演算法流程 |
| 鉤子方法 | 抽象類 | 可選 | 條件分支、預設行為、擴展點 |
java.io.InputStream.read(byte[]) 模板方法呼叫抽象 read()。java.util.AbstractList.addAll(int, Collection) 模板方法呼叫抽象 add(int, E)。javax.servlet.http.HttpServlet.service() 分發到 doGet/doPost 等抽象方法。