深入理解設計模式之:代理模式
一、什么是代理模式?
代理模式(Proxy Pattern)是一種結構型設計模式。它為其他對象提供一種代理以控制對這個對象的訪問。代理對象在客戶端和目標對象之間起到中介作用,可以在不改變目標對象的前提下,增強或控制對目標對象的訪問。
二、代理模式的應用場景
- 權限控制:如用戶訪問權限校驗
- 延遲加載:如大對象的懶加載
- 遠程代理:如RPC、RMI
- 日志記錄:如方法調用日志
- 緩存代理:如結果緩存
- 防火墻代理:如網絡請求過濾
三、代理模式的分類
-
靜態代理
代理類在編譯時就已經確定,代碼量較大,靈活性較差。 -
動態代理
代理類在運行時動態生成,Java 中常用 JDK 動態代理和 CGLIB 動態代理。
四、代理模式的結構
- Subject(抽象主題):定義目標對象和代理對象的共同接口
- RealSubject(真實主題):實現了 Subject 的真實對象
- Proxy(代理對象):實現了 Subject,內部持有 RealSubject 的引用
五、靜態代理實現示例(Java)
1. 定義接口
public interface UserService {void login(String username, String password);
}
2. 實現真實主題
public class UserServiceImpl implements UserService {@Overridepublic void login(String username, String password) {System.out.println(username + " 登錄系統,密碼:" + password);}
}
3. 實現代理類
public class UserServiceProxy implements UserService {private UserService realService;public UserServiceProxy(UserService realService) {this.realService = realService;}@Overridepublic void login(String username, String password) {// 代理增強:如權限校驗、日志System.out.println("【代理】開始登錄校驗...");realService.login(username, password);System.out.println("【代理】登錄操作已記錄日志。");}
}
4. 客戶端調用
public class Main {public static void main(String[] args) {UserService realService = new UserServiceImpl();UserService proxy = new UserServiceProxy(realService);proxy.login("Tom", "123456");}
}
輸出結果:
【代理】開始登錄校驗...
Tom 登錄系統,密碼:123456
【代理】登錄操作已記錄日志。
六、JDK 動態代理實現示例
1. 定義接口和真實主題(同上)
2. 創建動態代理處理器
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class UserServiceInvocationHandler implements InvocationHandler {private Object target;public UserServiceInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("【動態代理】方法調用前...");Object result = method.invoke(target, args);System.out.println("【動態代理】方法調用后...");return result;}
}
3. 客戶端調用
public class Main {public static void main(String[] args) {UserService realService = new UserServiceImpl();UserService proxy = (UserService) Proxy.newProxyInstance(realService.getClass().getClassLoader(),realService.getClass().getInterfaces(),new UserServiceInvocationHandler(realService));proxy.login("Alice", "password");}
}
輸出結果:
【動態代理】方法調用前...
Alice 登錄系統,密碼:password
【動態代理】方法調用后...
七、代理模式的優缺點
優點:
- 職責清晰,擴展性好
- 可以在不修改目標對象的前提下增強功能
- 控制對象訪問,保護目標對象
缺點:
- 增加系統復雜度
- 靜態代理類過多,維護成本高
- 動態代理對理解和調試有一定門檻
八、總結
代理模式是實際開發中非常常用的設計模式,Spring AOP、MyBatis Mapper、RPC 框架等都大量用到代理思想。掌握代理模式有助于理解 Java 動態代理、AOP 等高級特性。
建議:
- 簡單增強可用靜態代理,復雜場景優先用動態代理
- 結合實際業務場景選擇合適的代理方式
如需更多設計模式講解或源碼分析,歡迎留言交流!