代理是另一种结构设计模式 ,可以“代表”另一个对象或“代替”另一个对象以访问后面的对象。
何时使用此模式?
当我们需要创建一个包装来覆盖客户端的主要对象的复杂性时,将使用代理模式。
有哪些使用场景?
- 虚拟代理–设想一种情况,其中有多个数据库调用来提取大尺寸图像。 由于这是一项昂贵的操作,因此我们可以使用代理模式,该模式将创建多个代理并指向庞大的内存消耗对象进行进一步处理。 仅当客户端首先请求/访问该对象时,才创建真实对象,然后,我们可以仅引用代理来重用该对象。 这避免了对象的重复,从而节省了内存。
- 远程代理–可以将远程代理视为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