Proxy是代理、委任的意思,因此Proxy模式就是指访问对象时使用代理对象的设计模式。Proxy这个词是从网络上使用的Proxy浏览器联想出来的。并不是用Netscape或者IE等Web浏览器直接访问Web浏览器的,而是通过代理的 Proxy浏览器。Proxy浏览器的目的就是为了减轻网络安全性能及现金带来的网络负担。
Proxy模式的Proxy分为以下三种。
remote proxy是访问类似分散对象的网络上其他浏览器对象时,隐藏IP地址或协议等网络相关的信息,程序如本地对象一样处理的模式。
virtual proxy生成对象时,因为对象过大等原因,不希望加载实体时,假定为Proxy而实际并生成对象。
例如,在处理图像的Web浏览器程序中,第一次不需要将画面表示出来。这时候,仅仅通过将网页内的画面对象作为Proxy生成,替换表示画面的模式,画面被删除的时候,加载实体并表示出来。因此,才能提高网页初期显示的速度,节约程序的记忆库消耗。
protection proxy是解决访问对象时的安全性问题。要访问的对象在不希望被所有对象直接访问时,Proxy创建一个访问用的对象,然后仅允许该对象访问。
Apple公司(以前的Next公司) OpenStep环境的InterfaceBuilder的delegate性能等就是最好的例子。通过Proxy来控制访问,在顾客/服务器・系统等分散环境中是非常重要的。接下来举一个Proxy模式的例子。
接下来来看一下如图3所示的文字处理机软件中处理画像的应用。
与virtual proxy例子中介绍的Web浏览器一样,文字处理机的应用在打开文件时不显示图像,将图像模式设置为ON,删除图像时显示出来。文件中有图像时,只生成图像Proxy对象不生成实体的图像对象。从画图像开始,生成实体的图像对象后加载文件然后进行组装。 那来看一下如图4所示的类图。
因为在该程序中使用了Java的GUI结构AWT,图像类的超类则变成了AWT的Panel类。在ImageDisplay、ImageDisplayProxy类中改写Panel类中的paint()。
在Java的Applet编程中,因为已经规定好了init()、start()、stop()、run()、paint()、update ()等方法,所以必须写出相对应的编码。此外,Java中的编程除了要学习Java语言,更需要活用这些方法构成的结构。
Java语言虽然被认为是很简单且容易理解,但是Java程序员却很少,大概是因为跨越这个障碍很难吧。因为本连载不是Java编程的讲座,下面回到正题。继续边看Java编码边进行阐述。
Proxy例的Java编码
class ImageDisplayProxy extends Panel {
ImageDisplay imgp;
Applet apl;
String imagefile;
ImageDisplayProxy(Applet applet, String filename) {
apl = applet;
imagefile = filename;
}
public void update(Graphics g) {
paint(g);
}
ImageDisplay getImage(){
if (imgp == null){
imgp = new ImageDisplay(apl,imagefile);
}
return imgp;
}
public void paint(Graphics g) {
getImage().paint(g,this);
}
}
class ImageDisplay extends Panel {
Image img;
ImageDisplay(Applet applet, String filename) {
img = applet.getImage(applet.getCodeBase(),filename);
}
public void paint(Graphics g,Panel ip) {
g.drawImage(img, 0, 0, ip);
super.paint(g);
}
}
Proxy例的主要部分
public class ProxyPattern extends Applet {
public void init() {
setLayout(new BorderLayout());
ImageDisplayProxy idp = new ImageDisplayProxy(this,"images/yellow_box.jpg");
add("Center", idp);
}
}
在主要部分的init()中,new ImageDisplayProxy()生成了图像Proxy对象。在ImageDisplayProxy类的结构ImageDisplayProxy()中,只需用Applet名称和图像文件名保存不需要加载图像实体。而且当需要更新主要部分的Applet时,就生成ImageDisplayProxy类的update()。
在update()中,生成paint(),然后当做getImage().paint()。这里很关键,如果还没有生成imgp,getImage()就会用new ImageDisplay()加载实体。因为有imgp == null这个条件,就不会发生二次加载。然后再生成getImage()的返回值-ImageDisplay对象的paint()方法。该paint()中,通过drawImage()、paint()在Applet上进行绘图。
这个是virtual proxy的例子,但是Proxy模式在用CORBA、ActiveX、RMI等分散对象进行应用开发时非常有用,在美国应用的非常广泛。