Proxy模式

Proxy模式

Proxy是代理、委任的意思,因此Proxy模式就是指访问对象时使用代理对象的设计模式。Proxy这个词是从网络上使用的Proxy浏览器联想出来的。并不是用Netscape或者IE等Web浏览器直接访问Web浏览器的,而是通过代理的 Proxy浏览器。Proxy浏览器的目的就是为了减轻网络安全性能及现金带来的网络负担。

Proxy模式的Proxy分为以下三种。

  • remote proxy
  • virtual proxy
  • protection 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等分散对象进行应用开发时非常有用,在美国应用的非常广泛。