代理模式是一种结构型设计模式,它允许通过一个代理对象控制对其他对象的访问。代理模式引入了一定程度的间接性,使得可以在访问对象前后进行一些额外的操作。代理模式通常包含三个主要角色:抽象主题(Subject)、真实主题(RealSubject)和代理(Proxy)。
代理模式通常在以下场景中使用:
远程代理:
当需要在不同地址空间中访问对象时,可以使用远程代理。远程代理在本地代理和远程对象之间充当中介,使得客户端可以通过代理访问远程对象。
虚拟代理:
当需要延迟创建或初始化对象时,可以使用虚拟代理。虚拟代理在真正需要使用对象时才创建或初始化,可以提高系统的性能。
保护代理:
当需要控制对对象的访问权限时,可以使用保护代理。保护代理通过对客户端的访问进行控制,限制了对真实主题的直接访问。
缓存代理:
当需要缓存对象的访问结果时,可以使用缓存代理。缓存代理在访问真实主题之前检查缓存,如果缓存中存在结果,则直接返回缓存的结果,否则访问真实主题并将结果缓存起来。
下面通过一个简单的例子来演示代理模式的实现。假设有一个图像加载器,加载大图像可能会耗费较长时间,我们可以使用代理模式来引入一个代理对象,控制对图像加载的访问。
抽象主题 - 图像接口 Image
package com.cheney.demo;
interface Image {
void display();
}
真实主题 - 真实图像 RealImage
package com.cheney.demo;
class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadImageFromDisk();
}
private void loadImageFromDisk() {
System.out.println("从硬盘加载图片: " + filename);
}
@Override
public void display() {
System.out.println("显示图片: " + filename);
}
}
代理 - 图像代理 ImageProxy
package com.cheney.demo;
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();
}
}
客户端启动类 Main
package com.cheney.demo;
public class Main {
public static void main(String[] args) {
// 使用代理模式加载图像
Image image = new ImageProxy("large_image.jpg");
// 第一次显示图像
image.display();
// 第二次显示图像(不会再次加载,直接显示缓存的结果)
image.display();
}
}
在上述例子中,Image
是抽象主题,定义了图像的接口。RealImage
是真实主题,实现了抽象主题接口,表示真实的图像。ImageProxy
是代理,实现了抽象主题接口,包含一个指向真实主题的引用,控制对真实主题的访问。
在客户端中,我们使用代理模式加载图像。第一次显示图像时,代理对象会创建并初始化真实主题,并显示图像。第二次显示图像时,代理对象直接显示缓存的结果,无需再次加载。
代理模式是一种结构型设计模式,通过引入一个代理对象,可以控制对其他对象的访问。在实际开发中,代理模式常被用于实现远程代理、虚拟代理、保护代理、缓存代理等场景。通过合理使用代理模式,可以提高系统的灵活性、可维护性,并且降低客户端与真实对象之间的耦合。