代理是另一種結構設計模式 ,可以“代表”另一個對象或“代替”另一個對象以訪問后面的對象。
何時使用此模式?
當我們需要創建一個包裝來覆蓋客戶端的主要對象的復雜性時,將使用代理模式。
有哪些使用場景?
- 虛擬代理–設想一種情況,其中有多個數據庫調用來提取大尺寸圖像。 由于這是一項昂貴的操作,因此我們可以使用代理模式,該模式將創建多個代理并指向龐大的內存消耗對象進行進一步處理。 僅當客戶端首先請求/訪問該對象時,才創建真實對象,然后,我們可以僅引用代理來重用該對象。 這避免了對象的重復,從而節省了內存。
- 遠程代理–可以將遠程代理視為RPC調用中的存根。 遠程代理提供了在不同地址位置中存在的對象的本地表示。 另一個示例可以是為遠程資源(例如Web服務或REST資源)提供接口。
- 保護性代理–保護性代理充當授權層,以驗證實際用戶是否有權訪問適當的內容。 可以考慮一個有關在辦公室中提供受限Internet訪問的代理服務器的示例。 僅允許使用有效的網站和內容,其余的將被阻止。
- 智能代理–智能代理通過在訪問對象時插入特定操作來提供附加的安全層。 一個示例可以是在訪問真實對象之前檢查它是否已鎖定,以確保沒有其他對象可以更改它。
結構體:
代理設計模式結構
參加者:
- 主題–此對象定義RealSubject和Proxy的通用接口,以便可以在需要RealSubject的任何地方使用Proxy。
- 代理–維護對RealSubject的引用,以便代理可以訪問它。 它還實現了與RealSubject相同的接口,因此可以使用Proxy代替RealSubject。 代理還控制對RealSubject的訪問,并且可以創建或刪除此對象。
- RealSubject –這是代理代表的主要對象。
例:
我們將在本文中討論兩個示例。 第一個是虛擬代理模式,另一個是保護代理模式。
虛擬代理示例 :
如前所述,虛擬代理對于節省昂貴的內存資源很有用。 讓我們以實際圖像包含客戶端需要訪問的巨大數據為例。 為了節省我們的資源和內存,實現如下:
- 創建一個供客戶端訪問的接口。 其所有方法將由ProxyImage類和RealImage類實現。
- RealImage在其他系統上運行,并且包含可從數據庫訪問的圖像信息。
- 在其他系統上運行的ProxyImage可以在新系統中表示RealImage。 使用代理,我們可以避免多次加載圖像。
類圖:
虛擬代理示例
代碼示例:
圖像.java
public interface Image {public void showImage();
}
RealImage.java
public class RealImage implements Image {private String fileName = null; public RealImage(String strFileName){this.fileName = strFileName;}@Overridepublic void showImage() {System.out.println('Show Image:' +fileName);}
}
ProxyImage.java
public class ProxyImage implements Image {private RealImage img= null;private String fileName = null;public ProxyImage(String strFileName) {this.fileName = strFileName;}/** (non-Javadoc)* @see com.proxy.virtualproxy.Image#showImage()*/@Overridepublic void showImage() {if(img == null){img = new RealImage(fileName);}img.showImage();}
}
客戶端程序
public class Client {
public static void main(String[] args) {final Image img1 = new ProxyImage('Image***1');final Image img2 = new ProxyImage('Image***2');img1.showImage();img2.showImage();}
}
保護代理示例:
- 假設ABC公司啟動了一項新政策,即根據其角色現在禁止員工訪問Internet。 所有外部電子郵件網站將被阻止。 在這種情況下,我們創建InternetAccess接口,該接口由操作GrantInternetAccess()組成。
- RealInternetAccess類,允許所有人訪問互聯網。 但是,為了限制此訪問,我們將使用ProxyInternetAccess類,該類將檢查用戶的角色并根據其角色授予訪問權限。
類圖:
保護代理示例
代碼示例:
互聯網:
public interface InternetAccess {public void grantInternetAccess();
}
RealInternetAccess.java
public class RealInternetAccess implements InternetAccess {private String employeeName = null;public RealInternetAccess(String empName) {this.employeeName = empName;}@Overridepublic void grantInternetAccess() {System.out.println('Internet Access granted for employee: '+ employeeName);}
}
ProxyInternetAccess.java
public class RealInternetAccess implements InternetAccess {private String employeeName = null;public RealInternetAccess(String empName) {this.employeeName = empName;}@Overridepublic void grantInternetAccess() {System.out.println('Internet Access granted for employee: '+ employeeName);}
}
客戶端程序
public static void main(String[] args) {InternetAccess ia = new ProxyInternetAccess('Idiotechie');ia.grantInternetAccess();}
優點:
- 如您在上面的示例中看到的,代理模式的優點之一是關于安全性。
- 這種模式避免了對象的重復,這些對象可能是巨大的并且占用大量內存。 反過來,這可以提高應用程序的性能。
- 遠程代理還通過在客戶端計算機上安裝本地代碼代理(存根),然后借助遠程代碼訪問服務器來確保安全性。
缺點/后果:
這種模式引入了另一層抽象,如果某些客戶端直接訪問RealSubject代碼,而其中一些可能訪問Proxy類,則有時可能會遇到問題。 這可能會導致不同的行為。
有趣的一點:
- 相關模式之間幾乎沒有差異。 就像Adapter模式為其主題提供不同的接口,而Proxy模式提供與原始對象相同的接口,而裝飾器提供增強的接口。 裝飾器模式在運行時添加了其他行為。
- Java API中使用的代理:java.rmi。*;
請不要忘記發表您的評論。 如果您喜歡本文,請通過社交網絡鏈接為您的朋友分享此文章。
下載示例代碼:
參考: Idiotechie博客上來自JCG合作伙伴 Mainak Goswami 的“四人幫–代理設計模式” 。
翻譯自: https://www.javacodegeeks.com/2012/11/gang-of-four-proxy-design-pattern.html