设计模式之代理模式
代理,一般人都知道是什么意思,代理是一种行为,在客户不想或不能直接操作时,把操作交付给代理来处理,代理模式亦是如此,代理模式是一种典型的行为型设计模式,想完成的行为引出了代理模式,其实现方法倒是不拘泥。
代理模式定义为:为其他对象提供一种代理以控制对这个对象的访问。简单的说就是,不直接引用一个对象,而代理对象可以在客户和目标对象之间起到中介作用,并且可以去掉客户不能看到的内容和服务或者增添客户需要的额外服务。听上去有点儿装饰模式的味道,^^
代理模式根据使用目的、情景、方式等不同有很多种类,最常见的也是最重要的有如下几种:
1) 远程(Remote)代理:为一个位于不同的地址空间的对象提供一个局域代表对象。比如:你可以将一个在世界某个角落一台机器通过代理假象成你局域网中的一部分。
2) 虚拟(Virtual)代理:根据需要将一个资源消耗很大或者比较复杂的对象延迟的真正需要时才创建。比如:如果一个很大的图片,需要花费很长时间才能显示出来,那么当这个图片包含在文档中时,使用编辑器或浏览器打开这个文档,这个大图片可能就影响了文档的阅读,这时需要做个图片Proxy 来代替真正的图片(缩略图的意味)。
3) 保护(Protect or Access)代理:控制对一个对象的访问权限。比如:在论坛中,不同的身份登陆,拥有的权限是不同的,使用代理模式可以控制权限(当然,使用别的方式也可以实现)。
4) 智能引用(Smart Reference)代理:提供比对目标对象额外的服务。比如:纪录访问的流量(这是个再简单不过的例子),提供一些友情提示等等。
代理模式使用之广泛,从几个类的小结构,到庞大系统的大结构都可以看到其活跃的影子。
来看看代理模式抽象出来的结构图:
代理模式主要由三个角色组成:
1) 抽象主题角色:声明了真实主题和代理主题的共同接口。
2) 代理主题角色:内部包含对真实主题的引用,并且提供和真实主题角色相同的接口。
3) 真实主题角色:定义真实的对象。
当然这是一种典型的代理模式结构,上面说过代理模式实现方式多种多样,视具体情况不同而不同。
举个栗子,^^
以论坛中已注册用户和游客的权限不同来作为第一个例子:已注册的用户拥有发帖、修改自己的注册信息、修改自己的帖子等功能;而游客只能看到别人发的帖子,没有其他权限。为了简化代码,更好的显示出代理模式的骨架,我们这里只实现发帖权限的控制。
首先我们先实现一个抽象主题角色 MyForum,里面定义了真实主题和代理主题的共同接口——发帖功能。
1 public interface MyForum{
2 public void AddFile();
3 }
这样,真实主题角色和代理主题角色都要实现这个接口。其中真实的主题角色基本就是将这个接口的方法内容填充进来。所以在这里就不再赘述它的实现。我们把主要的精力放到关键的代理主题角色上。代理主题角色代码大体如下:
1 public class MyForumProxy implements MyForum{
2 private RealMyForum forum = new RealMyForum() ;
3 private int permission ; //权限值
4 public MyForumProxy(int permission){
5 this.permission = permission ;
6 }
7 //实现的接口
8 public void AddFile(){
9 //满足权限设置的时候才能够执行操作
10 //Constants 是一个常量类
11 if(Constants.ASSOCIATOR == permission){
12 forum.AddFile();
13 }else
14 System.out.println("You are not a associator of MyForum ,please
15 registe!");
16 }
17 }
18 }
代理模式能够协调调用者和被调用者,能够在一定程度上降低系统的耦合度。代理模式中的真实主题角色可以结合组合模式来构造,这样一个代理主题角色就可以对一系列的真实主题角色有效,提高代码利用率,减少不必要子类的产生。