摘要:本文深入浅出的讲述了设计模式中的代理模式 , 并给出了简单的示例 , 例子浅显易懂 , 并附带源代码。 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

代理模式属于结构型模式。意图是为其他对象提供一种代理以控制对这个对象的访问。控制对象的访问主要体现在是只有在我们确实需要这个对象时才对他进行创建和初始化。比如在文档中嵌入的图形对象的文档编辑器。有些对象的创建开销很大,但是打开文档必须很迅速,因此我们在打开文档时应该避免一次性创建所有开销很大的对象。因为并非所有这些对象在文档中都同时可见,所以也没有必要同时创建这些对象。对于每一个开销很大的对象,应该根据需要进行创建,当一个图像变为可见时会产生这样的需要,但是在文档中我们使用什么来代替这个图像哪,我们又如何才能隐藏根据需要创建图像这一事实,从而不会使得编辑器的实现复杂化哪?这里使用Proxy模式很好的解决了这个问题。
1

例如:一个显示图片的选项卡程序,每一个选项卡显示一幅图片,在任何一个时刻,只有一个选项卡被选中,因此在没有选中的选项卡中的图片就没有必要被创建,使用一个图片的代理对象代理这个图片,只要在客户端程序要求显示这个图像时才真正创建该图像,在代理对象中必须存储被代理对象的所有的信息。

适用性:在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用 Proxy 模式,

1.      远程代理,为一个对象在不同的地址空间提供局部代表

2.      虚代理 根据需要创建开销很大的对象。

3.      保护代理 控制队员是对象的访问。保护代理用于对象应该有不同的访问权限的时候。

4.      智能指引 取代了简单的指针,他在访问对象时执行一些附加操作。主要的用途包括:对指向实际对象的引用计数,这样当该对象没有引用时,可以自动释放。当第一次引用一个持久对象时,将它装入内存。在访问一个实际对象前,检查是否已经锁定了它,以确保其他对象不能改变它。

参与者:

    Proxy(p_w_picpathProxy):

           -- 保存一个引用时的代理可以访问实体,若 ReadSubject Subject 的借口相同, Proxy 会引用 Subject

           提供一个与 Subject 的接口相同的接口,这样代理就可以用来代替实体。

           控制对实体的存取,并可能负责创建和删除。

       Subject(Icon): 定义 ReadSubject Proxy 公用的接口,这样在任何使用 RealSubject  的地方都可以使用 Proxy.

       RealSubject(Image): 定义 Proxy 所代表的实体。

他们的协作关系是:代理根据其种类,在适当的时候向 RealSubject 转发请求。

相关的代码: Image Icon 的代码使用 JDk 自带的类 .

ImageProxy 类:

    package proxy;

import javax.swing.*;

import java.awt.*;

 

public class  ImageProxy implements Icon {

  public ImageProxy(String name){

    this.name = name;

    p_w_picpath = null;

  }

  public int getIconHeight() {

    ensureImageLoaded();

    return p_w_picpath.getIconHeight();

  }

  public int getIconWidth() {

    ensureImageLoaded();

    return p_w_picpath.getIconWidth();

  }

  public void paintIcon(Component component, Graphics graphics, int n, int n1) {

    ensureImageLoaded();

    p_w_picpath.paintIcon(component, graphics, n, n1);

  }

  private void ensureImageLoaded(){

    if (p_w_picpath == null) {

      System.out.println("Loading " + name);

      p_w_picpath = new ImageIcon("proxy/"+name);

    }

  }

  private String name;

  private ImageIcon p_w_picpath;

}

客户端代码:

    package proxy;

import javax.swing.JTabbedPane;

import javax.swing.JLabel;

import javax.swing.JFrame;

import java.awt.Container;

public class Client{

  public static void main(String[] args){

    JTabbedPane tabbedPane = new JTabbedPane();

    for (int i = 0;i < p_w_picpathNames.length; i++) {

      JLabel label = new JLabel(new ImageProxy(p_w_picpathNames[i]));

      tabbedPane.add(p_w_picpathNames[i], label);

    }

    JFrame frame = new JFrame();

    Container contentPane = frame.getContentPane();

    contentPane.add(tabbedPane);

 

    frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    frame.show();

 

  }

 

  private static final String[] p_w_picpathNames = {

    "gogo16.gif" ,

    "gogo17.gif" ,

    "gogo18.gif" ,

    "gogo19.gif" ,

    "gogo20.gif" ,

    "gogo21.gif" ,

    "gogo22.gif" ,

    "gogo23.gif" ,

    "gogo24.gif" ,

    "gogo25.gif" ,

    "gogo26.gif" ,

    "gogo27.gif" ,

    "gogo28.gif" ,

    "gogo29.gif" ,

    "gogo30.gif" ,

    "another.gif"

  };

  private static final int FRAME_WIDTH = 500;

  private static final int FRAME_HEIGHT = 300;

}

总结: Proxy 模式在访问对象是引入了一定程度的间接性,根据代理的类型,附加的间接性有多种用途:  

1.      Remote Proxy 可以隐藏一个对象存在于不同抵制空间的事实。

2.      Virtual Proxy 可以进行最优化,例如根据要求创建对象。

3.      Protection Proxies Smart Reference 都允许在访问一个对象时有一些附加的内务处理。