代理模式

1.代理模式动机及定义

1.1模式动机

        某人要找对象,但是由于某些原因(如工作太忙)不能直接去找,于是委托一个中介机构去完成这一过程,如婚姻介绍所,在这里婚姻介绍所就是一个代理,与此相类似的还有房屋中介,职业中介,它们充当的都是一个代理的角色。所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动。在我们所开发的软件系统中有时候也存在这样的情况,如调用一个远程的方法,需要在本地设置一个代理,使得就像调用本地方法一样来使用远程的方法,这实际上就是RMI,Web Service等的实现原理。

        在某些情况下,一个客户不想或者不能直接引用一个对象,此时可以通过一个称之为“代理”的第三者来实现间接引用。代理对象可以在客户端和目标之间起到中介的作用,并且可以通过代理对象去掉客户不能看到的内容和服务或者添加客户需要的额外服务。

        如在网页上查看一张图片,由于网速等原因图片不能立即显示,可以在图片传输过程中先把一些简单的用于描述图片的文字(或者小图片)传输到客户端,此时这些文字(或者小图片)就成为了图片的代理。

        再举一个例子,如果某台远程服务器提供了一个功能强大的加密算法,而现在正在开发的系统又需要使用到该算法,由于该算法位于远程服务器端,封装该算法的对象就位于远程服务器的内存中,本地内存中的对象无法直接访问,因此需要通过一个远程代理的机制来实现对远程对象的操作。

        以上两个例子都引入了一个新的对象(如小图片和远程代理对象)来实现对真实对象的操作或者将新的对象作为真实对象的一个替身,这种实现机制即为代理模式,通过引入代理对象来间接访问一个对象,这就是代理模式的动机。

1.2模式定义

        代理模式(Proxy Pattern)定义:给某一个对象提供一个代理,并由代理对象控制对原对象对引用。代理模式对英文叫做Proxy或Surrogate,它是一种对象结构型模式。

        英文定义:“Provide a surrogate or placeholder for another object to control access to it.”

2.代理模式结构与分析

2.1模式结构

 

图1 代理模式结构图

代理模式包含如下角色。

1.Subject(抽象主题角色)

        抽象主题角色声明了真实主题和代理主题的共同接口,这样一来在任何使用真实主题的地方都可以使用代理主题。客户端需要针对抽象主题角色进行编程。

2.Proxy(代理主题角色)

        代理主题角色内部包含对真实主题对引用,从而可以在任何时候操作真实主题对象。在代理主题角色中提供一个与真实主题角色相同的接口,以便在任何时候都可以替代真实主体。代理主题角色还可以控制对真实主题的使用,负责在需要的时候创建和删除真实主题对象,并对真实主题对象的使用加以约束。代理角色通常在客户端调用所引用的真实主题操作之前或之后还需要执行其他操作,而不仅仅是单纯的调用真实主题对象中的操作。

3.RealSubject(真实主题角色)

        真实主题角色定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色间接调用真实主题角色中定义的方法。

3.代理模式实例与解析

        题目:应用软件所提供的桌面快捷方式时快速启动应用程序的代理,桌面快捷方式一般使用一张小图片来表示,通过调用快捷方式的run方法讲调用应用程序软件Application的run方法,使用代理模式模拟该过程,试绘制类图并编程实现。

3.1实例类图

 

3.2实例代码及解释

1.抽象主题角色Subject(抽象主题类)

public interface Subject {

    void run();

}

        Subject是作为抽象主题类,充当了抽象主题角色,在其中声明了真实角色主题角色所提供的run()方法,它是真实主题角色和代理主题角色的公共接口。

2.代理主题角色Picture(图片类)

public class Picture implements Subject{

    private Application app = new Application();

    @Override

    public void run() {

        System.out.println("Picture is called");

        app.run();

    }

}

        Picture是代理主题角色,它也实现了抽象主题角色的接口,同时在Picture中定义了一个Application对象,用于调用在Application中定义的真实业务方法。

3.真实主题角色Application(应用类)

public class Application implements Subject{

    @Override

    public void run() {

        System.out.println("Application 正在运行!");

    }

}

        Application是真实主题角色,它实现了在抽象主题角色中定义的方法,由于种种原因,客户端无法直接访问其中的方法。在Application中包含了run()方法的实现。

3.3辅助代码

客户端测试类Client如下:

public class Client {

    public static void main(String[] args) {

        Subject p =new Picture();

        p.run();

    }

}

3.4结果

 

4.代理模式效果与应用

4.1 代理模式的优点

        (1)代理模式能够协调调用者和被调用者,在一定程度上降低了系统的耦合度。

        (2)远程代理使得客户端可以访问在远程机器上的对象,远程机器可能具有更好的计算性能与处理速度,可以快速响应并处理客户端请求。

        (3)虚拟代理通过使用一个小对象来代表一个大对象,可以减少系统资源的消耗,对系统进行优化并提高运行速度。

        (4)保护代理可以控制对真实对象的使用权限。

4.2代理模式的缺点

        (1)由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。

        (2)实现代理模式需要额外的工作,有些代理模式的实现非常复杂。

4.3模式适用环境

在以下情况可以使用代理模式。

  1. 远程(Remote)代理:为一个位于不同的地址空间的对象提供一个本地的代理对象,这个不同的地址空间可以是在同一台主机中,也可以是在另一个主机中,远程代理又叫做大使(Ambassador)。
  2. 虚拟(Virtual)代理:如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。
  3. Copy-on-Write代理:它是虚拟代理的一种,把复制(克隆)操作延迟到只有在客户端真正需要时才执行。一般来说,对象的深克隆是一个较大的操作,Copy-on-Write代理可以让这个操作延迟,只有对象被用到的时候才被克隆。
  4. 保护(Protect or Access)代理,控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。
  5. 缓冲(Cache)代理:为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。
  6. 防火墙(Firewall)代理:保护目标不让恶意用户接近。
  7. 同步化(Synchronization)代理:使几个用户能够同时使用一个对象而没有冲突。
  8. 智能引用(Smart Reference)代理:当一个对象被引用时,提供一些额外的操作,如将此对象被调用的次数记录下来等。

        在这些种类的代理中,虚拟代理、远程代理和保护代理是最常见的代理模式。不同类型的代理模式有不同的优缺点,它们应用于不同的场合。

更多推荐