代理模式定義
代理模式(Proxy Pattern) 是一種結(jié)構(gòu)型設(shè)計模式跑揉。
- 為其他對象提供一種代理待讳,以控制對這個對象的訪問品擎。
- 代理對象在客戶端和目標(biāo)對象之間起到中介作用,可以在不修改目標(biāo)對象的情況下,增強或控制對其的訪問全陨。
基本概念
- 代理對象(Proxy):實現(xiàn)與目標(biāo)對象相同的接口爆班,持有對目標(biāo)對象的引用,負責(zé)在必要時創(chuàng)建或訪問目標(biāo)對象辱姨。
- 目標(biāo)對象(Real Subject):實際執(zhí)行業(yè)務(wù)邏輯的對象蛋济,是代理對象所代表的真實實體。
- 客戶端(Client):通過代理對象間接地與目標(biāo)對象交互炮叶,不直接訪問目標(biāo)對象碗旅。
代理模式的類型
代理模式根據(jù)實現(xiàn)方式和應(yīng)用場景的不同,可以分為以下幾種類型:
- 遠程代理(Remote Proxy):為位于不同地址空間的對象提供本地代表镜悉,隱藏實際對象在遠程的事實祟辟。常用于分布式系統(tǒng)中的遠程方法調(diào)用(RMI)。
- 虛擬代理(Virtual Proxy):根據(jù)需要創(chuàng)建開銷很大的對象侣肄,通過代理來控制對象的創(chuàng)建和初始化旧困。常用于懶加載場景。
- 保護代理(Protection Proxy):控制對目標(biāo)對象的訪問稼锅,根據(jù)權(quán)限進行限制吼具。常用于權(quán)限管理系統(tǒng)。
- 智能引用代理(Smart Reference Proxy):在訪問目標(biāo)對象時矩距,執(zhí)行一些額外的操作拗盒,如引用計數(shù)、日志記錄等锥债。
- 動態(tài)代理(Dynamic Proxy):在運行時動態(tài)生成代理類陡蝇,不需要預(yù)先定義代理類。常用于 AOP(面向切面編程)等場景哮肚。
使用場景
- 遠程方法調(diào)用:需要訪問位于遠程的對象登夫,通過代理對象隱藏網(wǎng)絡(luò)通信的細節(jié)。
- 懶加載:需要延遲創(chuàng)建資源密集型的對象允趟,通過代理控制對象的創(chuàng)建時機恼策。
- 權(quán)限控制:根據(jù)用戶的訪問權(quán)限,控制對目標(biāo)對象的訪問潮剪。
- 日志記錄或性能監(jiān)控:在調(diào)用目標(biāo)對象的方法時涣楷,增加日志或監(jiān)控功能。
- 事務(wù)管理:在方法調(diào)用前后增加事務(wù)處理邏輯鲁纠。
示例代碼
以下示例演示了虛擬代理的應(yīng)用总棵,模擬一個圖片查看器鳍寂,延遲加載高分辨率的圖片文件改含。
1. 定義抽象主題接口
// 圖片接口
public interface Image {
void display();
}
2. 實現(xiàn)真實主題類
// 真實的圖片類
public class RealImage implements Image {
private String fileName;
public RealImage(String fileName) {
this.fileName = fileName;
loadFromDisk(fileName); // 模擬加載圖片
}
private void loadFromDisk(String fileName) {
System.out.println("加載圖片:" + fileName);
}
@Override
public void display() {
System.out.println("顯示圖片:" + fileName);
}
}
3. 實現(xiàn)代理類
// 圖片代理類
public class ProxyImage implements Image {
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName) {
this.fileName = fileName;
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(fileName); // 延遲加載
}
realImage.display();
}
}
4. 客戶端代碼
public class Client {
public static void main(String[] args) {
Image image = new ProxyImage("test_10mb.jpg");
// 圖片將被加載并顯示
image.display();
System.out.println("");
// 圖片已加載,不會再次加載迄汛,直接顯示
image.display();
}
}
輸出結(jié)果:
加載圖片:test_10mb.jpg
顯示圖片:test_10mb.jpg
顯示圖片:test_10mb.jpg
說明:
- 第一次調(diào)用
display()
方法時捍壤,代理類ProxyImage
檢查realImage
是否已創(chuàng)建骤视,若未創(chuàng)建則創(chuàng)建并加載圖片。 - 第二次調(diào)用
display()
方法時鹃觉,圖片已加載专酗,直接顯示,不再重復(fù)加載盗扇。
優(yōu)勢
- 控制對象的訪問:代理模式可以在不修改目標(biāo)對象的情況下祷肯,控制對其的訪問權(quán)限和方式。
- 降低系統(tǒng)開銷:通過延遲加載等方式疗隶,減少資源消耗佑笋,提高系統(tǒng)性能。
- 增強目標(biāo)對象功能:在目標(biāo)對象的方法調(diào)用前后增加額外的功能斑鼻,如日志蒋纬、事務(wù)等。
- 高擴展性:代理對象和目標(biāo)對象都實現(xiàn)相同的接口坚弱,符合開閉原則蜀备,便于擴展和維護。
代理模式的意義
- 解耦客戶端與目標(biāo)對象:客戶端通過代理對象與目標(biāo)對象交互荒叶,不直接依賴于目標(biāo)對象的實現(xiàn)碾阁,降低了系統(tǒng)的耦合度。
- 符合單一職責(zé)原則:代理對象負責(zé)處理非業(yè)務(wù)功能些楣,如權(quán)限控制瓷蛙、日志記錄等,目標(biāo)對象專注于業(yè)務(wù)邏輯戈毒,實現(xiàn)職責(zé)分離艰猬。
- 靈活性和可維護性:可以在不修改目標(biāo)對象的情況下,動態(tài)地添加功能埋市,滿足業(yè)務(wù)需求的變化冠桃。
代理模式與裝飾器模式的區(qū)別
-
目的不同:
- 代理模式:主要用于控制對目標(biāo)對象的訪問,可能在訪問前后執(zhí)行某些操作道宅,側(cè)重于控制食听。
- 裝飾器模式:主要用于為對象動態(tài)地添加新功能,增強對象的功能污茵,側(cè)重于功能擴展樱报。
-
實現(xiàn)方式不同:
- 代理模式:代理對象持有目標(biāo)對象的引用,客戶端通過代理對象間接地訪問目標(biāo)對象泞当。
- 裝飾器模式:裝飾器和被裝飾對象都實現(xiàn)相同的接口迹蛤,裝飾器持有被裝飾對象的引用,可以在方法調(diào)用前后進行功能擴展。
-
使用場景不同:
- 代理模式:適用于遠程代理盗飒、虛擬代理嚷量、保護代理、智能引用等場景逆趣。
- 裝飾器模式:適用于需要動態(tài)添加對象功能的場景蝶溶,如 Java I/O 中的各種流的包裝。
總結(jié)
代理模式提供了一種間接訪問對象的方式宣渗,通過在代理對象中控制對目標(biāo)對象的訪問抖所,可以實現(xiàn)延遲加載、權(quán)限控制痕囱、日志記錄等功能部蛇。在實際開發(fā)中,代理模式廣泛應(yīng)用于遠程方法調(diào)用咐蝇、事務(wù)管理等領(lǐng)域和
AOP(面向切面編程)涯鲁。
啟示:
最明顯的就是 - 中介
現(xiàn)實場景:在日常生活中,我們經(jīng)常通過中介或代理來完成某些任務(wù)有序,例如房地產(chǎn)中介抹腿、律師代理、經(jīng)紀人等旭寿。他們作為專業(yè)的代理人警绩,幫助我們處理復(fù)雜的事務(wù),節(jié)省時間和精力盅称。
代理模式在生活和社會中的應(yīng)用肩祥,反映了專業(yè)化分工、資源優(yōu)化缩膝、權(quán)限控制混狠、信息安全等重要原則。
- 合理分配職責(zé):通過代理來處理特定的任務(wù)疾层,可以提高效率将饺,發(fā)揮專業(yè)優(yōu)勢。
- 控制訪問與保護:適當(dāng)?shù)臋?quán)限控制和信息屏蔽痛黎,可以保障安全和隱私予弧。
- 優(yōu)化資源利用:通過延遲加載和按需提供,避免資源浪費湖饱,提高利用率掖蛤。
- 促進溝通合作:代理作為橋梁,連接不同的主體井厌,促進協(xié)作與共贏蚓庭。
在現(xiàn)代社會中致讥,事務(wù)的復(fù)雜性和專業(yè)化程度不斷提高。理解并應(yīng)用代理模式的思想彪置,可以幫助我們更好地組織工作拄踪、管理資源蝇恶、保障安全拳魁,推動個人和社會的進步。