Java设计模式之代理模式篇(1) 在软件工程中,代理模式(Proxy Pattern)在很多情况下都非常有用。例如在Java XML保重,开发人员可以利用代理来访问Web服务。例1中演示了经典的Hello World Web服务的例子:
例1 一个SOAP代理的例子
public class HelloClient { public static void main(String[] args) { try { HelloIF_Stub proxy = (HelloIF_Stub)(new HelloWorldImpl().getHelloIF()); proxy._setTargetEndpoint(args[0]); System.out.println(proxy.sayHello("Hello World!")); } catch (Exception ex) { ex.printStackTrace(); } } } |
在例一中,客户端首先获得对代理的引用,然后利用命令行参数设定代理的端点(即Web服务的URL地址),接下来调用代理的sayHello()方法,代理再将方法调用传递给相应的Web服务。
代理模式和修饰模式(Decorator Pattern)有一定的相似之处。两个模式又使用了代理将方法调用传递给另一个对象,该对象被称为真实对象(Real Subject)。代理模式和修饰模式的不同之处在于:在代理模式中,代理和真实对象之间的关系在程序被编译的时候就确定下来了,而修饰模式则是在运行时递归地创建。
本文首先提供一个ImageIcon的例子来说明代理模式,然后会探讨一下JDK是如何支持代理模式的。
代理模式
代理模式通过使用代理来替代实际的对象,使程序能够控制对该对象的访问。下面是一个ImageIcon的例子。
例2 ImageIcon的例子
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class IconTest extends JFrame { private static String IMAGE_NAME = "hands.jpg"; private static int FRAME_X = 150, FRAME_Y = 200, FRAME_WIDTH = 430, FRAME_HEIGHT = 392; private Icon imageIcon = null, imageIconProxy = null; static public void main(String args[]) { IconTest app = new IconTest(); app.show(); } public IconTest() { super("ImageIcon测试"); imageIcon = new ImageIcon(IMAGE_NAME); setBounds(FRAME_X, FRAME_Y, FRAME_WIDTH, FRAME_HEIGHT); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } public void paint(Graphics g) { super.paint(g); Insets insets = getInsets(); imageIcon.paintIcon(this, g, insets.left, insets.top); } } |
 图1 ImageIcon测试
在上面的例子中程序创建了一个javax.swing.ImageIcon对象,并且重载了paint()方法来显示图标。例二中的代码有一些缺陷,在程序中开发人员只能够使用比较小的图片。因为创建一个图形会耗费很多系统资源,而ImageIcon的实例是在初始化时就创建包含在其中的图形对象。如果程序需要在较短的时间内显示很多比较大的图形对象,系统就有可能处理不过来。同时如果应用程序没有使用到这些图形,在前台创建这些图形对于系统资源来说也是一种浪费。
一个更好的解决方案是在需要显示图形的时候再加载图形。为了达到这个目的,可以通过利用代理来实现。当代理的paintIcon()方法第一次被调用时,程序才创建图形。图二中显示了一个既包含ImageIcon(左)又包含ImageIcon代理(右)的例子。在图二中上面一幅图中显示了程序刚加载时的情形。由于ImageIcon对象在初始化的时候就需要加载图形,因此当窗口出现时图片就显示在窗口的左边。而ImageIcon代理中的图片要到第一次被绘制时才会被调用。图二中下面一幅图显示了两幅图片都被加载后的情景。

 图2 ImageIcon和ImageIcon代理 (未完待续)
|