首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 設計模式精講:模板方法模式—— 定義算法骨架,延遲具體步驟到子類

     編輯:Java 綜合教學

前言:設計模式是軟件工程的基石

設計模式是經過分類、歸納、總結的代碼設計經驗。合理運用模式能實現代碼復用、提升可讀性、保證可靠性。本文聚焦行為型模式中的模板方法模式,通過源碼級解析與實戰案例,掌握其「定義骨架、延遲細節」的精髓。

一、設計模式全景速覽(23 種經典分類)

創建型(5 種)

  • 單例:全局唯一實例
  • 抽象工廠:創建相關對象族
  • 工廠方法:延遲實例化到子類
  • 建造者:分離複雜對象構建與表示
  • 原型:拷貝克隆創建新對象

行為型(11 種)

  • 模板方法:本文重點—— 定義算法骨架,子類實現具體步驟
  • 策略:算法族封裝互換
  • 觀察者:一對多依賴自動通知
  • 迭代器:統一遍歷聚合對象
  • 命令:請求對象化,支持撤銷/隊列/日志
  • 狀態:內部狀態改變行為
  • 職責鏈:多對象處理請求解耦
  • 中介者:封裝對象交互
  • 訪問者:不改類新增操作
  • 解釋器:語言文法解釋
  • 備忘錄:捕獲/恢復內部狀態

結構型(7 種)

  • 代理:控制對象訪問
  • 適配器:接口轉換兼容
  • 裝飾器:動態增強職責
  • 組合:樹形結構部分-整體
  • 外觀:高層統一接口
  • 橋接:抽象與實現分離
  • 享元:共享細粒度對象

二、模板方法模式深度解析

2.1 核心意圖

在一個操作中定義算法的骨架,將某些步驟延遲到子類實現。模板方法使得子類可以不改變算法結構的前提下,重新定義算法的某些特定步驟。

2.2 角色結構

角色職責
AbstractClass(抽象類)實現模板方法,定義算法骨架;聲明抽象方法強制子類實現
ConcreteClass(具體類)實現抽象方法,完成完整算法

2.3 代碼實戰:數據導出流程標準化

場景:系統需支持 Excel、CSV、PDF 多種導出格式,流程固定為「數據查詢 → 格式轉換 → 文件寫入 → 响應下載」,其中「格式轉換」與「文件寫入」因格式而異。

// 抽象模板:定義導出算法骨架
public abstract class AbstractExporter<T> {
    // 模板方法:final 防止子類破壞流程
    public final void export(List<T> data, HttpServletResponse response) {
        // 1. 通用預處理(設置響應頭等)
        prepareResponse(response);
        // 2. 核心變化點:格式轉換(子類實現)
        byte[] content = convert(data);
        // 3. 通用後處理(寫入輸出流)
        writeResponse(content, response);
        // 4. 釩勾子方法:子類可選覆寫
        afterExport();
    }

    protected void prepareResponse(HttpServletResponse response) {
        response.setContentType(getContentType());
        response.setHeader("Content-Disposition", "attachment; filename=" + getFileName());
    }

    protected void writeResponse(byte[] content, HttpServletResponse response) throws IOException {
        try (OutputStream os = response.getOutputStream()) {
            os.write(content);
            os.flush();
        }
    }

    // 抽象方法:強制子類實現
    protected abstract String getContentType();
    protected abstract String getFileName();
    protected abstract byte[] convert(List<T> data);

    // 鉤子方法:默認空實現,子類可選覆寫
    protected void afterExport() {}
}

// 具體實現:Excel 導出
public class ExcelExporter<T> extends AbstractExporter<T> {
    @Override protected String getContentType() { return "application/vnd.ms-excel"; }
    @Override protected String getFileName() { return "export_" + System.currentTimeMillis() + ".xls"; }
    @Override protected byte[] convert(List<T> data) {
        // 使用 Apache POI 實現 Excel 生成邏輯
        return workbookToBytes(data);
    }
}

// 具體實現:CSV 導出
public class CsvExporter<T> extends AbstractExporter<T> {
    @Override protected String getContentType() { return "text/csv"; }
    @Override protected String getFileName() { return "export_" + System.currentTimeMillis() + ".csv"; }
    @Override protected byte[] convert(List<T> data) {
        // CSV 字符串拼接邏輯
        return csvToBytes(data);
    }
}

2.4 關鍵設計要點

  1. 模板方法加 final:防止子類覆寫破壞算法骨架順序。
  2. 抽象方法 vs 鉤子方法:
    — 抽象方法(abstract):必須由子類實現(如 convert())
    — 鉤子方法(默認空實現):子類可選覆寫(如 afterExport()),提供擴展點不強制實現。
  3. 好萊塢原則:「別調用我們,我們會調用你」—— 父類調用子類實現,控制反轉雛形。

三、JDK 源碼中的經典應用

  • java.io.InputStream.read():模板方法調用抽象 read(byte[])
  • java.util.AbstractList.indexOf():模板遍歷調用抽象 get(int)
  • javax.servlet.http.HttpServlet.service():分發 doGet/doPost 等抽象方法
  • Spring JdbcTemplate、RestTemplate 大量使用模板方法封裝資源管理、異常轉換等通用邏輯

四、優缺點與適用場景

優點缺點
  • 提取公共代碼,便於維護
  • 控制算法流程,子類只實現細節
  • 符合開閉原則:新增子類擴展,不修改父類
  • 實現好萊塢原則,控制反轉
  • 每個不同實現需新增子類,類數量膨脹
  • 繼承關係耦合度高,父類修改影響所有子類
  • 不適用於算法骨架頻繁變化場景

適用場景:多個子類共享相同算法結構,僅局部步驟不同;複雜算法核心穩定、邊緣變化;框架設計中定義不可變的業務流程骨架。

五、總結

模板方法模式以「骨架在父類、血肉在子類」的優雅方式,實現了最大程度的代碼復用與最小程度的耦合。掌握其「抽象方法強制實現、鉤子方法可選覆寫、模板方法 final 守護」三大設計精髓,是構建可擴展框架級代碼的關鍵技能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved