设计模式之代理模式

代理模式英文名叫Proxy Pattern

看下Proxy的含义

[ˈprɑ:ksi]

n.代表权;代理人,代替物;委托书;

主要表达的就是代表、代替、委托的意思。

我对这个模式的理解是这样的:

一个服务或者是一个功能,一个对象。由于某种自身或者外界的原因,不能直接暴露出来,而是需要另外一个对象做一下跳转(也不一定是完全的跳转)。并且在这个过程中,最终实现功能或者是解决问题的实体并没有发生改变。

光说概念的话会比较抽象,我们举几个生活中的例子:

1>房产中介

如果户主打算拍卖掉房子,因此需要每天发广告、发消息,然后接待买家看房,和买家讨价还价。

这样的模式,相对来说比较简单,(也是很多新手喜欢的直接)。但是户主需要和每一个买家都进行接触。增加一个新的买家,就需要重新试探。流失一个买家,又有实时跟踪。这导致作为卖家的户主所要处理的事情越来越腌肿,买家关注了太多自己只用一次或者根本用不到的技能。

因此就需要引入一个代理:房产中介。

卖家将房子的信息:钥匙、报价、区间、卖房时间等整体告诉中介后。中介将所有的信息进行处理后公布出来。买房人再从中介处获取到自己所需要的信息,然后再通过中介与卖家沟通。

这样卖家就不需要再关注任何买房动态。只需要按照事先自己考虑的结果与代理进行商议即可。

2>明星经纪人

无论是娱乐明星还是体育明星,都需要有一个经纪人,或者有一个工作室。(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )这个工作室负责包装明星,制造舆论新闻,代表明星与制片方或者俱乐部谈判。而这些都不是明星需要直接关注的事情。明星任何的商务活动(谈判、签约等),都是通过代理人与外界进行接触的。

3>办事处

对于跨国企业来说,涉及到的业务往往是全球化的,很多业务往来存在政治、地区、时差等限制。因此有时这些机构就设置一个办事处,用来作为这些企业在当地的一个委托人,来治谈业务等。

这样做很好的体现出了对内提高内聚、对外降低耦合:

户主、明星、跨国企业都可以最大限度的聚焦于自身业务对外;(内聚)

户主、明星、跨国企业都不再需要过多的感知外界业务,通过代理这一层进行封装过滤,将真正属于户主(过户)、明星(演出)、跨国企业(生产制造)的业务传递给被代理人来操作。而对于外界来说大部分情况下,外界调用者并不感知到代理的存在,所有的事情与直接和被代理人谈是一样的。(解耦)

模式的结构可以理解为下图的样子:

  

可以看出代理方和被代理方都实现了一个对外接口。

这个接口是被代理方所有展示的所有方法。

调用方持有该接口的实现:代理人。

然后请求代理,代理再透传给该接口的另外一个实现:被代理人。真正的操作由被代理人来实现。(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )

可以通过如下代码来深度理解代理模式:

 调用方

 1 public class Invoker
 2 {
 3     public static void main(String[] args)
 4     {
 5         ISuperStar ronaldo = new SuperStarProxy("ronaldo");
 6         ronaldo.negotiate();
 7         ronaldo.signContract();
 8         ISuperStar messi = new SuperStarProxy("messi");
 9         messi.negotiate();
10         messi.signContract();
11     }
12 }

代理类

 1 public class SuperStarProxy implements ISuperStar
 2 {
 3     private ISuperStar superStar = new SuperStar();
 4     private String superStarName;
 5     
 6     public SuperStarProxy(String superStarName)
 7     {
 8         this.superStarName = superStarName;
 9         
10     }
11     
12     @Override
13     public void signContract()
14     {
15         superStar.signContract();
16     }
17     
18     @Override
19     public void negotiate()
20     {
21         superStar.negotiate();
22     }
23     
24 }

被代理类

 1 public class SuperStar implements ISuperStar
 2 {
 3     @Override
 4     public void signContract()
 5     {
 6         // to do sth
 7         return;
 8     }
 9     
10     @Override
11     public void negotiate()
12     {
13         // to do sth
14         return;
15     }
16 }

接口

 1 public interface ISuperStar
 2 {
 3     /**
 4      * 签约
 5      */
 6     public void signContract();
 7     
 8     /**
 9      * 谈判
10      */
11     public void negotiate();
12 }

 

代理模式的几个用途:

1、进行安全代理控制

被代理方和调用方有时存在于两个不同的安全域中,我们需要通过一个安全过滤鉴权的管道进行控制。这种情况下就可以使用代理来完成安全鉴权的功能。

举个例子:比如公司的外网访问,有时需要设置一个网络代理

2、虚拟代理进行延迟加载

有时初始化数据时,需要过多的初始化数据时,可以通过代理延缓这种加载,等到真正调用时,再初始化。举个例子:有时用流量看公众号文章时,如果是GIF,系统会暂时只加载一个静态的图片,当用户确定要看该GIF时,再点击图片,加载真正的GIF,静态的图片就相当于是一个虚拟代理。

3、远程工作代理

有时我们要调用网络另外一侧的一个接口,每一个开发者都需要自己实现一个该远程网络的交互,交互方式是千差万别的。这时我们就会使用一个远程的工作代理,这个代理就是一个接口的实现。我们可以先使用该代理进行开发,同时开发者也感知不到接口真正的工作状态。当我们调用这个远程的代理时,代理在内部就自动的与远程的接囗进行交互。而本地的业务逻辑并不能感知到。

举个例子:数据库包中的JDBC,该包由数据库厂商提供,我们的业务代码只和JDBC进行交互,并不会直接使用各种网络协议与数据库进行交互

4、管控

有时我们需要添加接口访问日志、接口耗时、频次等。就可以在原有实现的基础上,加一层代理。将这些逻辑推倒代理中实现,降低业务实现类的代码污染。

代理模式的缺点:

通过代理模式,我们可以看出,该模式在内聚封装的同时,将一部分的业务逻辑移植到了代理人处。虽然降低了调用方和实现方之间的耦合,但是加入了一层新的耦合,就是代理方和调用方之间的耦合。当有任何逻辑变更时,都需要修改代理方,因此代理模式在降低耦合的同时,会导致代理类变得越来越雕肿、业务越来越复杂。

5、(防盗连接:本文首发自http://www.cnblogs.com/jilodream/ )

扩展:

由于代理方也是接口的实现方,随着接口的变化,代理方都需要添加新的逻辑实现。而这种实现需要在系统运行前就已经搭配,并实现完成。因此这种模式也称为静态代理模式。我们在这个时候,需要支持一种动态的,最好可以一劳永逸的代理方式。这种方式可以支持简单的相同的逻辑处理,之后就直接进行透传即可。这种代理模式我们称之为动态代理。这个我会在后边的文章中介绍。

 

posted @ 2019-03-27 22:40  王若伊_恩赐解脱  阅读(805)  评论(0编辑  收藏  举报