代理模式是一种结构设计模式,它允许一个对象充当另一个对象的接口。代理通常控制着对于实际对象的访问,并且允许你在访问对象时添加额外的功能,比如验证、缓存等。
结构
- 主题接口(Subject): 定义了代理和真实对象的共同接口,这样在任何使用真实对象的地方都可以使用代理。
public interface Subject {
void request();
}
- 真实主题类(Real Subject): 实现了主题接口,定义了代理所代表的真实对象。
public class RealSubject implements Subject {
public void request() {
System.out.println("Real Subject is handling the request.");
}
}
- 代理类(Proxy): 实现了主题接口,并且持有一个对真实主题对象的引用,负责控制访问真实对象。
public class Proxy implements Subject {
private RealSubject realSubject;
public Proxy(RealSubject realSubject) {
this.realSubject = realSubject;
}
public void request() {
// 添加额外功能
System.out.println("Proxy is handling the request.");
// 委托给真实主题对象处理请求
realSubject.request();
}
}
优点和缺点
优点:
- 代理对象可以控制实际对象的访问: 代理对象可以在调用实际对象之前或之后执行一些操作,比如权限控制、缓存、日志等。
- 降低了系统的耦合度: 代理对象可以在不改变实际对象的前提下,对外提供统一的接口,降低了系统的耦合度。
- 实现了延迟加载: 当需要大量初始化资源或者网络资源时,代理可以在需要时才进行加载,实现了延迟加载,提高了系统的性能和响应速度。
缺点:
- 增加了代码的复杂度: 由于引入了代理对象,系统会变得更加复杂。
- 可能降低系统的性能: 如果代理对象过于复杂,可能会引起性能问题,特别是在频繁调用时。
示例
假设我们有一个图像加载器,但是由于图像较大,我们希望在真正需要显示图像时再进行加载。我们可以使用代理模式实现延迟加载:
// 主题接口
public interface Image {
void display();
}
// 真实主题类
public class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("Loading image: " + filename);
}
public void display() {
System.out.println("Displaying image: " + filename);
}
}
// 代理类
public class ProxyImage implements Image {
private RealImage realImage;
private String filename;
public ProxyImage(String filename) {
this.filename = filename;
}
public void display() {
if (realImage == null) {
realImage = new RealImage(filename);
}
realImage.display();
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
Image image = new ProxyImage("example.jpg");
// 图像在此时并未加载
image.display();
// 图像在此时加载并显示
}
}
在这个例子中,ProxyImage 充当了 RealImage 的代理,它负责在需要时创建真正的 RealImage 对象,并调用其 display 方法。这样,当我们调用 display 方法时,代理会在需要时加载真实对象,实现了延迟加载。