概述
代理模式是软件工程中一种常用的设计模式,属于结构型设计模式的一种。该模式通过提供一个代理对象来控制对真实对象的访问,从而实现诸如延迟初始化、访问控制、增加额外功能或减少客户与真实对象之间的耦合度等目的。代理模式的核心思想在于“代劳”,即客户端不是直接与目标对象交互,而是通过代理对象这个中介来进行。
目的
远程代理(Remote Proxy):为位于不同地址空间的对象提供局部代表,以便隐藏网络细节,简化远程对象的访问。
虚拟代理(Virtual Proxy):延迟创建重型对象,直到真正需要时才加载,提高系统性能。
保护代理(Protection Proxy):控制对原始对象的访问,用于访问控制,如权限验证。
缓存代理(Cache Proxy):为结果提供临时存储空间,如果重复请求相同数据,直接从缓存中返回结果,提高效率。
智能指引(Smart Reference):在引用对象的同时,执行一些额外操作,如计数、日志记录等。
应用场景
当需要为对象的访问添加一些控制逻辑时(如权限验证)。
需要动态地为对象添加功能,而又不希望修改对象的代码时。
对象的创建开销较大,希望通过代理延迟其初始化过程。
系统需要对客户端访问的真实对象进行远程访问或者需要进行分布式处理时。
需要对方法调用的结果进行缓存以优化性能。
结构与实现
结构
代理模式通常包含以下角色:
Subject(抽象主题):声明了RealSubject和Proxy的共同接口,使得在任何使用RealSubject的地方都可以使用Proxy。
RealSubject(真实主题):实现了Subject接口,定义了代理所表示的真实对象。
Proxy(代理):也实现了Subject接口,持有一个对RealSubject的引用,并通过此引用来调用真实对象的方法。可以在调用过程中添加额外的操作。
实现示例
以下是一个简单的Java实现示例,展示了如何使用代理模式来控制对一个图像文件的访问,并实现延迟加载功能。
// 抽象主题: Image
interface Image {
void display();
}
// 真实主题: RealImage
class RealImage implements Image {
private String fileName;
public RealImage(String fileName) {
this.fileName = fileName;
loadFromDisk(fileName);
}
private void loadFromDisk(String fileName) {
System.out.println("Loading " + fileName);
}
@Override
public void display() {
System.out.println("Displaying " + fileName);
}
}
// 代理: ImageProxy
class ImageProxy implements Image {
private RealImage realImage;
private String fileName;
public ImageProxy(String fileName) {
this.fileName = fileName;
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(fileName);
}
realImage.display();
}
}
// 客户端代码
public class ProxyPatternDemo {
public static void main(String[ ] args) {
Image image = new ImageProxy("test.jpg");
image.display(); // 第一次显示,会加载图片
image.display(); // 第二次显示,直接从内存中显示,无需再次加载
}
}
在这个例子中,ImageProxy
作为代理,在第一次调用display()
方法时才创建并加载RealImage
对象,之后的调用则直接使用已加载的图像,实现了延迟加载的效果。
总结
代理模式是一种灵活的设计模式,通过引入代理对象,可以在不修改原有对象的基础上,增加额外的功能或控制对对象的访问。它广泛应用于各种软件开发场景中,特别是需要进行远程访问、延迟初始化、访问控制和性能优化的情况。正确应用代理模式可以有效提升系统的灵活性和可维护性。
评论区