Intent

为其他对象提供一种代理,以控制对这个对象的访问。

Class Diagram

代理有以下四类:

  • 远程代理(Remote Proxy):控制对远程对象(不同地址空间)的访问,它负责将请求及其参数进行编码,并向不同地址空间中的对象发送已经编码的请求。
  • 虚拟代理(Virtual Proxy):根据需要创建开销很大的对象,它可以缓存实体的附加信息,以便延迟对它的访问,例如在网站加载一个很大图片时,不能马上完成,可以用虚拟代理缓存图片的大小信息,然后生成一张临时图片代替原始图片。
  • 保护代理(Protection Proxy):按权限控制对象的访问,它负责检查调用者是否具有实现一个请求所必须的访问权限。
  • 智能代理(Smart Reference):取代了简单的指针,它在访问对象时执行一些附加操作:记录对象的引用次数;当第一次引用一个对象时,将它装入内存;在访问一个实际对象前,检查是否已经锁定了它,以确保其它对象不能改变它。

image.png

Implementation

以下是一个虚拟代理的实现,模拟了图片延迟加载的情况下使用与图片大小相等的临时内容去替换原始图片,直到图片加载完成才将图片显示出来。
image.png

  1. // Subject
  2. public interface Image {
  3. void showImage();
  4. }
  1. // RealSubject
  2. public class HighResolutionImage implements Image {
  3. private URL imageURL;
  4. private long startTime;
  5. private int height;
  6. private int width;
  7. public int getHeight() {
  8. return height;
  9. }
  10. public int getWidth() {
  11. return width;
  12. }
  13. public HighResolutionImage(URL imageURL) {
  14. this.imageURL = imageURL;
  15. this.startTime = System.currentTimeMillis();
  16. this.width = 600;
  17. this.height = 600;
  18. }
  19. public boolean isLoad() {
  20. // 模拟图片加载,延迟 3s 加载完成
  21. long endTime = System.currentTimeMillis();
  22. return endTime - startTime > 3000;
  23. }
  24. @Override
  25. public void showImage() {
  26. System.out.println("Real Image: " + imageURL);
  27. }
  28. }
  1. // 继承自Subject,作为RealSuject的代理
  2. // client不会直接访问RealSuject,而是访问代理
  3. public class ImageProxy implements Image {
  4. private HighResolutionImage highResolutionImage;
  5. // 通过构造函数将RealSuject传入
  6. public ImageProxy(HighResolutionImage highResolutionImage) {
  7. this.highResolutionImage = highResolutionImage;
  8. }
  9. @Override
  10. public void showImage() {
  11. // 对被代理对象执行一些操作
  12. // 原图没有加载完成,则使用与图片大小相等的临时内容去替换原始图片
  13. while (!highResolutionImage.isLoad()) {
  14. try {
  15. System.out.println("Temp Image: " + highResolutionImage.getWidth() + " " + highResolutionImage.getHeight());
  16. Thread.sleep(100);
  17. } catch (InterruptedException e) {
  18. e.printStackTrace();
  19. }
  20. }
  21. // 加载完成在显示原始图片
  22. highResolutionImage.showImage();
  23. }
  24. }
  1. public class ImageViewer {
  2. public static void main(String[] args) throws Exception {
  3. String image = "http://image.jpg";
  4. URL url = new URL(image);
  5. HighResolutionImage highResolutionImage = new HighResolutionImage(url);
  6. // 客户端访问代理来间接访问HighResolutionImage
  7. ImageProxy imageProxy = new ImageProxy(highResolutionImage);
  8. imageProxy.showImage();
  9. }
  10. }

JDK

  • java.lang.reflect.Proxy
  • RMI