【IT168 技术文档】代理模式属于结构型模式。意图是为其他对象提供一种代理以控制对这个对象的访问。控制对象的访问主要体现在是只有在我们确实需要这个对象时才对他进行创建和初始化。比如在文档中嵌入的图形对象的文档编辑器。有些对象的创建开销很大,但是打开文档必须很迅速,因此我们在打开文档时应该避免一次性创建所有开销很大的对象。因为并非所有这些对象在文档中都同时可见,所以也没有必要同时创建这些对象。对于每一个开销很大的对象,应该根据需要进行创建,当一个图像变为可见时会产生这样的需要,但是在文档中我们使用什么来代替这个图像哪,我们又如何才能隐藏根据需要创建图像这一事实,从而不会使得编辑器的实现复杂化哪?这里使用Proxy模式很好的解决了这个问题。
例如:一个显示图片的选项卡程序,每一个选项卡显示一幅图片,在任何一个时刻,只有一个选项卡被选中,因此在没有选中的选项卡中的图片就没有必要被创建,使用一个图片的代理对象代理这个图片,只要在客户端程序要求显示这个图像时才真正创建该图像,在代理对象中必须存储被代理对象的所有的信息。
适用性:在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用Proxy模式,
1. 远程代理,为一个对象在不同的地址空间提供局部代表
2. 虚代理 根据需要创建开销很大的对象。
3. 保护代理 控制队员是对象的访问。保护代理用于对象应该有不同的访问权限的时候。
4. 智能指引 取代了简单的指针,他在访问对象时执行一些附加操作。主要的用途包括:对指向实际对象的引用计数,这样当该对象没有引用时,可以自动释放。当第一次引用一个持久对象时,将它装入内存。在访问一个实际对象前,检查是否已经锁定了它,以确保其他对象不能改变它。
参与者:
Proxy(imageProxy):
--保存一个引用时的代理可以访问实体,若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; image = null; } public int getIconHeight() { ensureImageLoaded(); return image.getIconHeight(); } public int getIconWidth() { ensureImageLoaded(); return image.getIconWidth(); } public void paintIcon(Component component, Graphics graphics, int n, int n1) { ensureImageLoaded(); image.paintIcon(component, graphics, n, n1); } private void ensureImageLoaded(){ if (image == null) { System.out.println("Loading " + name); image = new ImageIcon("proxy/"+name); } } private String name; private ImageIcon image; }
客户端代码:
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 < imageNames.length; i++) { JLabel label = new JLabel(new ImageProxy(imageNames[i])); tabbedPane.add(imageNames[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[] imageNames = { "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都允许在访问一个对象时有一些附加的内务处理。