写点什么

代理模式

用户头像
soolaugust
关注
发布于: 2020 年 12 月 27 日
代理模式

我们在开发中会经常使用到别的库和代码。在使用时我们可能需要在方法上增加我们自己的业务逻辑。这个对于我们来说很简单,但是如果我们很多地方都需要用到这个业务逻辑。我们当然可以在每一个用到的地方都添加我们的业务逻辑,但是这明显会使得代码变得复杂。


那么我们可以封装我们使用的方法,然后再里面加入我们的逻辑。这样的话我们就可以很方便的根据我们的业务需要来使用这些方法。而这就是代理模式的一种应用场景。


image


那么什么是代理模式?在回答这个问题,我们可以想一下我们日常生活什么时候需要代理?这里我简单说一下几种代理场景:

  • 代理商:代理商一般都是拥有某一市场的资源,比如欧洲地区代理商。代理商的出现主要是因为对于厂商来说自身无法满足这一市场或者建设成本过高。那么代理商的出现正好可以满足这一市场的需要,可以根据这一市场的具体要求来指定产品的分发策略。

  • 平台代理:也就是像淘宝这种,因为有了这种,我们买东西不需要去一个个商家实体考察。因为淘宝已经帮我们做好了,我们可以按照价格或者自己的需要选购想要的商品。

  • 各种银行卡:各种银行卡其实是金钱的代理,因为我们以前都是带各种钱去买东西,但是当需要购买的东西价格很高时,我们背着一麻袋的钱去就显得很麻烦了,这时银行卡的出现就方便了我们的生活。无论金额多大,都只需要简单的一张卡。


我们可以看出我们需要代理的场景都是为了更好的使用代理后面的服务。记住这一句话:代理的出现还是为了使用其后面的服务。这个是区别其他构造型设计模式的根本。

应用场景

在上面我们说了生活中的代理场景,那么在代码中我们会在什么时候需要代理呢?

  • 服务对象过于庞大:当我们需要使用的服务是一个重量级对象时,我们不希望一开始就创建这个对象,这样对象会一直运行然后消耗资源。这时我们就可以使用代理模式,通过一个代理对象,在每次使用时才创建对象,在使用完进行销毁。这个时候代理就相当于原始服务对象的一个占位符,当需要使用时再来调用原始服务对象。

// 服务对象过于庞大public class TooLargeObject {    public TooLargeObject(){...} // 初始化    public boolean destroy(){...} // 销毁    public void method(){...} // 方法}
// 代理对象public class TooLargeObjectProxy { private TooLargeObject tooLargeObject; // 可以通过组合或者继承的方式引入,这里采用组合的方式 public void function(){ // 使用时才创建,使用完后进行销毁 tooLargeObject = TooLargeObject(); tooLargeObject.method(); tooLargeObject.destroy(); }}
复制代码
  • 使用服务需要进行额外的处理:很多时候我们使用服务需要增加额外的处理,比如在自己的业务上增加统计,日志,监控等功能。或者在引入外部的库和代码前后加入自己的业务逻辑。又或者对于自己的核心业务增加保护等等,凡是这种需要对使用的服务增加额外的处理,除了直接修改原有的服务,我们更应该考虑使用代理对象。

// 需要使用的服务public class Service {    public void method(){...}}
// 代理对象public class ServiceProxy extends Service { // 和上面不同的是,这里采用继承的方式 @Override public void method(){ preHandle(); // 前处理 super.method(); // 使用的服务方法 postHandle(); // 后处理 } private void preHandle(){...} private void postHandle(){...}}
复制代码


其他地方在讲解代理模式的应用场景会列很多地方,但是在我看来总结起来就是这两条,像其他所说的虚拟代理、智能引用都属于第一种情况,而像 RPC 服务中代理的网络处理、保护代理的前置验证处理以及日志,缓存的处理都属于第二种。代理模式的出现主要是为了解耦服务使用者和服务提供者,在它们中间增加一层代理层后可以有效的减少使用者的代码复杂度和避免对服务提供者的修改。

代理模式

按照设计模式的分析流程,我们来看一下代理模式的意图、动机、结构和代码实现。


演示文稿1.jpg


意图


动机


结构

代理模式的结构主要是两部分:原始对象和代理对象,如果是组合方式,可能还会存在一个统一的接口。如下图:


演示文稿1.png


代码实现

代理的实现方式其实很简单,总体上来说有两种:组合和继承。

  • 组合:组合主要适用于代理只需要原始服务对象的部分功能,如果和原始对象实现了相同的接口,那么替换起来就比较方便了。

  • 继承:这种一般是最为常见的方式,因为我们使用代理模式就是为了使用原始服务对象。所以一般继承可以使用原始服务对象的全部功能,并且根据我们的需要的进行修改。

除了上面的这种,还有一种是动态代理,主要是为了解决我们引用的组件或者功能太多,而处理逻辑基本相同,这样我们可以通过反射等方法来在实际调用时再修改逻辑。这种因具体语言来说实现难度不同,这里就不做具体的解决,感兴趣的可以上网查找相关资料。

上面我们使用了 Java 来实现两种方式代理模式的组合和继承两种实现方式。

总结

代理模式属于结构型设计模式的一种,主要是为了解决如何更好的使用服务这一目的。代理模式的实现上可以通过组合和继承。通过代理模式,可以将服务使用者和提供者进行解耦,并且在代理层,我们可以增加额外的操作来进行处理。当我们需要更改我们依赖的服务时,可以先考虑是否可以通过代理模式来避免修改源码。


推荐阅读


发布于: 2020 年 12 月 27 日阅读数: 21
用户头像

soolaugust

关注

公众号:雨夜随笔 2018.09.21 加入

公众号:雨夜随笔

评论

发布
暂无评论
代理模式