代理模式(Proxy Pattern)

z_coding發表於2024-05-28

代理模式(Proxy Pattern)

是程式設計中的一種設計模式,其主要作用是為其他物件提供一種代理,以控制對這個物件的訪問。以下是關於代理模式的詳細解釋:
代理模式定義:為其他物件提供一種代理以控制對這個物件的訪問。在某些情況下,一個物件不適合或者不能直接引用另一個物件,而代理物件可以在客戶端和目標物件之間起到中介的作用。

一、組成

  1. 抽象角色:透過介面或抽象類宣告真實角色實現的業務方法。
  2. 代理角色:實現抽象角色,是真實角色的代理,透過真實角色的業務邏輯方法來實現抽象方法,並可以附加自己的操作。
  3. 真實角色:實現抽象角色,定義真實角色所要實現的業務邏輯,供代理角色呼叫。

二、優點

  1. 職責清晰:真實的角色就是實現實際的業務邏輯,不用關心其他非本職責的事務,透過後期的代理完成一件完整事務,附帶的結果就是程式設計簡潔清晰。
  2. 中介和保護作用:代理物件可以在客戶端和目標物件之間起到中介的作用,起到了中介的作用和保護了目標物件的作用。
  3. 高擴充套件性:模式結構包括真正的你要訪問的物件(目標類)和代理物件,它們實現同一個介面,先訪問代理類再訪問真正要訪問的物件。

三、缺點

  1. 請求處理速度可能變慢:由於在客戶端和真實主題之間增加了代理物件,因此有些型別的代理模式可能會造成請求的處理速度變慢。
  2. 實現複雜度:實現代理模式需要額外的工作,有些代理模式的實現可能非常複雜。

四、實現方式

代理模式通常有兩種實現方式:靜態代理和動態代理。

  1. 靜態代理:在編譯時就已經確定代理類,代理類和目標類實現了相同的介面,客戶端透過代理類來呼叫目標類的方法。靜態代理需要手動編寫代理類,並且對於每個目標類都需要編寫一個對應的代理類,因此當目標類較多時,工作量會很大。
  2. 動態代理:動態代理是在執行時動態生成代理類,客戶端透過動態代理類來呼叫目標類的方法。Java 中提供了兩種動態代理的實現方式:基於介面的 JDK 動態代理和基於類的 CGLIB 動態代理。JDK 動態代理要求目標類必須實現一個或多個介面,而 CGLIB 動態代理則要求目標類不能被 final 修飾。

五、示例(以 JDK 動態代理為例)

以下是一個使用 JDK 動態代理實現代理模式的示例:

java
import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
import java.lang.reflect.Proxy;  
  
// 抽象主題角色  
interface Subject {  
    void request();  
}  
  
// 真實主題角色  
class RealSubject implements Subject {  
    @Override  
    public void request() {  
        System.out.println("RealSubject: Handling request.");  
    }  
}  
  
// 代理主題角色  
class ProxyHandler implements InvocationHandler {  
    private Object target;  
  
    public ProxyHandler(Object target) {  
        this.target = target;  
    }  
  
    @Override  
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
        before();  
        Object result = method.invoke(target, args);  
        after();  
        return result;  
    }  
  
    private void before() {  
        System.out.println("ProxyHandler: Before method call.");  
    }  
  
    private void after() {  
        System.out.println("ProxyHandler: After method call.");  
    }  
}  
  
// 客戶端程式碼  
public class Client {  
    public static void main(String[] args) {  
        RealSubject realSubject = new RealSubject();  
        InvocationHandler handler = new ProxyHandler(realSubject);  
  
        // 建立代理物件  
        Subject proxySubject = (Subject) Proxy.newProxyInstance(  
                RealSubject.class.getClassLoader(),  
                RealSubject.class.getInterfaces(),  
                handler  
        );  
  
        // 呼叫代理物件的方法  
        proxySubject.request();  
    }  
}

相關文章