通过使用Gmail,进一步理解软件设计模式中的代理模式(Proxy pattern).
Gmail邮箱的使用需求:
一直使用的邮箱A,所有的邮件进出的直接使用邮箱;
大量的团队邮箱C1,C2,C3,...,Cn;
以前被废弃的邮箱D1,D2,D3,...,Dm。
为了使用的方便,我们希望所有的团队邮箱中的邮件能够自动转发到A,被废弃的邮箱能够自动转发邮件到A。一般情况下,我们可以简单的通过让C系、D系邮箱自动转发到A,不支持转发的可以通过Gmail自带的邮件提取功能去主动提取邮件。
我们似乎看到了解决的方法,但是对于有“洁癖”的朋友可能发现这样的问题:
邮件e同时发送到A,C1,D1,则出现了A中出现了三封一样的邮件e,这样不论是视觉上还是空间上面都是一种浪费。能否将其过滤掉呢?在这个时候大家可能容易想到那些强大的邮件过滤器机制。但是经过尝试,你会发现随着n、m值的增多,我们可能需要在A中设置大量的复杂的过滤机制,这样我们就增加了日常邮件系统的维护。这让我们很容易想到请别的人帮我们做过滤,在公司中你可能会有机会被配一个秘书来做此事,但是更多的人可能就得自我来“人肉法”了。那么我们能否请一个自动秘书呢?通过这个思路,我们在直接给A转发各种邮件时,先通过一个秘书,让秘书做统一的过滤后做再次转发至A.
以上就是通过一个统一的过滤秘书B,来达到简洁处理的效果。以后再有C系、D系邮箱的增加,我们就直接让他们转发到秘书B那里就好了。
如此以来,我们简化了A的过滤规则,提高了以后扩展邮箱时的速度。 在这里我只是抛砖引玉,其实B中的过滤转发条件是丰富多样了,大家可以根据自己的具体需要来定制。
现在我们将解决方案引申,可以得到一种称为“代理”的广义社会生活的解决方案。
什么是代理?
代理基本上为财产法上概念,具一身专属性质的身分行为原则上不许代理;另外,侵权行为也不能代理。
1.委托代理,是基于被代理人的委托而发生的代理关系;
2.法定代理,是根据法律的直接规定而发生的代理关系;
3.指定代理,是根据人民法院和有关单位的指定而发生的代理关系。
代理人在代理权限内,以被代理人的名义进行民事活动,其法律后果直接由被代理人承受的法律制度。代理是三方人之间的民事法律关系,即代理人与被代理人之间的关系,代理人与第三人之间的关系,第三人与被代理人之间的关系。
代理的适用范围包括:
1.代理实施法律行为,如代理进行买卖、租赁、签订合同和履行债务等;
2.代理进行民事诉讼;
3.代理履行某些财政、行政义务,如代理进行房屋登记、法人登记、商标注册。纳税等。但某些具有人身性质的民事行为如婚姻登记、收养子女、立遗嘱等,以及某些具有人身性质的债务如约稿合同、演出合同等,依法须由本人亲自履行的,不能代理。此外,侵权行为和内容违法的行为,也不能进行代理。
在我理解,代理就是代替我们处理一些事务。
现在我们来看看设计模式中的经典设计模式之一“代理模式”。
我第一次看到代理模式,是在《Head First 设计模式》中看到的,里面的引入例子就是我们在Java中通常使用的RMI.其实我感觉这个例子不够生动,至少我使用这个东西的机会很少;后来我又在使用Spring时看到了大量使用代理模式的样例和具体使用场景,这里面的例子则及其生动的展现了一个代理的所作所为(从XML绑定,到后面的使用都体现了这个优秀的设计模式的优越性)。
......................................................
二、定义和分类
代理模式在设计模式中的定义就是:为其他对象提供一种代理以控制对这个对象的访问。说白了就是,在一些情况下客户不想或者不能直接引用一个对象,而代理对象可以在客户和目标对象之间起到中介作用,去掉客户不能看到的内容和服务或者增添客户需要的额外服务。
那么什么时候要使用代理模式呢?在对已有的方法进行使用的时候出现需要对原有方法进行改进或者修改,这时候有两种改进选择:修改原有方法来适应现在的使用方式,或者使用一个“第三者”方法来调用原有的方法并且对方法产生的结果进行一定的控制。第一种方法是明显违背了“对扩展开放、对修改关闭”(开闭原则),而且在原来方法中作修改可能使得原来类的功能变得模糊和多元化(就像现在企业多元化一样),而使用第二种方式可以将功能划分的更加清晰,有助于后面的维护。所以在一定程度上第二种方式是一个比较好的选择!
当然,话又说回来了,如果是一个很小的系统,功能也不是很繁杂,那么使用代理模式可能就显得臃肿,不如第一种方式来的快捷。这就像一个三口之家,家务活全由家庭主妇或者一个保姆来完成是比较合理的,根本不需要雇上好几个保姆层层代理:)
根据《Java与模式》书中对代理模式的分类,代理模式分为8种,这里将几种常见的、重要的列举如下:
1. 远程(Remote)代理:为一个位于不同的地址空间的对象提供一个局域代表对象。比如:你可以将一个在世界某个角落一台机器通过代理假象成你局域网中的一部分。
2. 虚拟(Virtual)代理:根据需要将一个资源消耗很大或者比较复杂的对象延迟的真正需要时才创建。比如:如果一个很大的图片,需要花费很长时间才能显示出来,那么当这个图片包含在文档中时,使用编辑器或浏览器打开这个文档,这个大图片可能就影响了文档的阅读,这时需要做个图片Proxy来代替真正的图片。
3. 保护(Protect or Access)代理:控制对一个对象的访问权限。比如:在论坛中,不同的身份登陆,拥有的权限是不同的,使用代理模式可以控制权限(当然,使用别的方式也可以实现)。
4. 智能引用(Smart Reference)代理:提供比对目标对象额外的服务。比如:纪录访问的流量(这是个再简单不过的例子),提供一些友情提示等等。
代理模式是一种比较有用的模式,从几个类的“小结构”到庞大系统的“大结构”都可以看到它的影子。
三、结构
代理模式中的“代理商”要想实现代理任务,就必须和被代理的“厂商”使用共同的接口(你可以想象为产品)。所以自然而然你会想到在java中使用一个抽象类或者接口(推荐)来实现这个共同的接口。于是代理模式就有三个角色组成了:
1.抽象主题角色:声明了真实主题和代理主题的共同接口。
2.代理主题角色:内部包含对真实主题的引用,并且提供和真实主题角色相同的接口。
3.真实主题角色:定义真实的对象。
使用类图来表示下三者间的关系如下:
当然,图上所示的是代理模式中的一个具体情况。而代理模式可以非常灵活的使用其他方式来实现,这样就与图上所示有很大的区别。
也许,现在你已经对代理模式已经有了一个宏观的认识了,下面我们来看看怎么实际的使用代理模
式
.........................
网上有很多讨论这个设计模式的文章,我的开发经验有限在这里就不献丑了。
总结:
- 设计模式不仅仅可以使用在软件设计中,更可以发挥我们的想像将它们使用到一切适用的地方。本身这一个个模式都来源于生活嘛。
- 充分利用网上的各个工具,力争使我们的工作生活娱乐“低耦合”、“高内聚”、“易扩展”。