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

Java 設計模式:計數代理模式深度解析

     編輯:Java 相關知識

模式動機

在軟體系統中,服務提供者(Real Subject)應專注於核心業務邏輯。但實際開發常需在方法呼叫前後加入日誌記錄、效能計數、存取控制等橫切關注點。若直接耦合在業務類中,會違反「單一職責原則」,導致程式碼膨脹且難以維護。

計數代理模式的核心思想:將這些附加功能封裝在獨立的代理物件中,代理實現與真實主題相同的介面,客戶端透過代理間接存取真實物件,代理在轉發呼叫前後執行額外邏輯。

結構圖解

計數代理模式類關係圖

圖中關鍵角色:

  • Subject (OrderIF):定義共同介面
  • RealSubject (Order):真實業務實作
  • Proxy (OrderProxy):持有 RealSubject 參考,實現同樣介面,攔截呼叫並執行計數/日誌

程式碼實戰

1. 定義共同介面

public interface OrderIF {
    Vector getAllOrders();
}

2. 真實主題:讀取訂單資料

public class Order implements OrderIF {
    public Vector getAllOrders() {
        FileUtil fileUtil = new FileUtil();
        return fileUtil.fileToVector("orders.txt");
    }
}

3. 計數代理:攔截並記錄效能指標

public class OrderProxy implements OrderIF {
    private int counter = 0;

    public Vector getAllOrders() {
        Order realOrder = new Order();
        counter++;

        long start = System.currentTimeMillis();
        Vector result = realOrder.getAllOrders();
        long elapsed = System.currentTimeMillis() - start;

        String logMsg = "Iteration=" + counter + "::Time=" + elapsed + "ms";
        new FileUtil().writeToFile("log.txt", logMsg, true, true); // 追加寫入

        return result;
    }
}

4. 客戶端使用:透明替換

public class MainApp {
    public static void main(String[] args) {
        OrderIF proxy = new OrderProxy(); // 客戶端只依賴介面
        proxy.getAllOrders();
        proxy.getAllOrders();
        proxy.getAllOrders();
        proxy.getAllOrders(); // 日誌將記錄 4 次呼叫及各自耗時
    }
}

模式優勢與適用場景

優勢說明
職責分離業務邏輯與輔助功能(日誌、計數、快取、權限檢查)解耦
開閉原則新增代理功能無需修改 RealSubject
透明性客戶端無感知代理存在,程式碼零修改切換
彈性組合可疊加多層代理(如:計數代理 → 快取代理 → 安全代理 → 真實物件)

適用場景:

  • 方法呼叫前後需統一執行:日誌、計時、計數、交易邊界、權限驗證
  • 遠端代理、虛擬代理、保護代理、智慧引用等變體
  • AOP(面向切面程式設計)的基礎實現形式之一

進階延伸:動態代理

Java 內建 java.lang.reflect.Proxy 與 InvocationHandler 可在執行期動態生成代理類,避免為每個介面手寫代理類。Spring AOP 底層即基於此機制(JDK 動態代理 / CGLIB)。

// 動態代理範例雛形
OrderIF proxy = (OrderIF) Proxy.newProxyInstance(
    OrderIF.class.getClassLoader(),
    new Class[]{OrderIF.class},
    (proxyObj, method, args) -> {
        long start = System.nanoTime();
        Object result = method.invoke(realOrder, args);
        log.info("{} 耗時 {} ms", method.getName(), (System.nanoTime()-start)/1e6);
        return result;
    }
);

總結

計數代理模式以「組合大於繼承」的思想,將橫切關注點從核心業務中剝離,是構建整潔、可維護、可擴展系統的基石模式之一。理解其靜態結構與動態代理演進,有助於深入掌握現代框架(Spring、Dubbo 等)的底層設計哲學。

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