实战:使用代理模式实现统一标准接口

原创 剑秋 人人架构师 2022-07-11 08:04 发表于四川

收录于合集#设计模式2个

本文章是一篇在真实业务场景中使用代理模式,面对业务场景如何使用代理模式去解决问题,主要是实战思路,所以对于代理模式的概念只会简单讲一下。

另外如果你觉得本文对你有用的话,请点个在看并且转发一下,只有得到支持才能写更好的文章。

很多人说学了设计模式用不来,唉,这不就跟我当初一样的嘛,设计模式各种文章,各种教程都看完了,我以为自己很厉害,结果在项目中还是TMD用不来,一句话,学了跟没学差不多。

后来为什么我会在项目中使用设计模式呢?就是必须在写代码的时候要思考这里能不能用设计模式,用哪种?这就是我的经验,一旦用熟了,自然而然就能想到,就不用思考了。

如果你已经了解了代理模式的概念,可以直接从我的业务场景开始看。

  • 1.什么是代理模式

为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

举个例子:Windows 里面的快捷方式。

在程序里,快捷方式就是一个对象,他应该没有行为啊,但是为什么能通过快捷方式打开软件?

真正能打开的应该是exe程序,所以可以看作是代理了exe程序,可以调用exe的行为。

优缺点:

1、代理模式能将代理对象与真实被调用的目标对象分离。

2、一定程度上降低了系统的耦合度,扩展性好。

3、可以起到保护目标对象的作用。

4、可以对目标对象的功能增强。

当然,代理模式也是有缺点的:

1、代理模式会造成系统设计中类的数量增加。

2、在客户端和目标对象增加一个代理对象,会造成请求处理速度变慢。

3、增加了系统的复杂度。

  • 2.JDK与CGLIB动态代理

1、jdk代理生成的代理类只有一个,因而其编译速度是非常快的;而由于被代理的目标类是动态传入代理类中的,Jdk代理的执行效率相对来说低一点,这也是Jdk代理被称为动态代理的原因;

2、Cglib代理需要为每个目标类生成相应的子类,因而在实际运行过程中,其可能会生成非常多的子类,过多的子类始终不是太好的,因为这影响了虚拟机编译类的效率;但由于在调用过程中,代理类的方法是已经静态编译生成了的,因而Cglib代理的执行效率相对来说高一些。

  • 3.我使用代理模式的业务场景

之前做项目需要对接监控视频平台,就是摄像头厂商会有一个开放给用户的api平台,供用户对接,以完成业务需要。例如我要获取某个监控视频的直播地址,获取监控设备的在线状态,都需要通过对接此api平台完成。

前期很长一段时间只对接了1个平台(每个厂商都有自己的平台),后来加入了另一个平台。

为什么会这样呢?因为我们的企业用户的监控设备来自于多个厂商,就需要对接多个厂商的API。

但是在监控设备管理前端,企业用户并不关心此监控设备是来自于哪个厂商,他只需要能看直播,完成指令下发就行了(例如控制监控设备旋转,抓拍图片,录像等等)

  • 4.整理需求

基于以上的场景,我们的开发人员会面临以下问题:

不同的厂商的api都不一样,接口请求地址和参数都不一样。

例如我获取监控设备列表,需要获取直播地址;我在数据库中查询出来设备列表,难道我要循环,然后判断这个监控设备属于哪个厂商的,再调用对应厂商的接口吗。

这还只是一个接口,当初我对接一个厂商的也有几十个接口,难道开发人员每次调用都需要写if eles吗?

5.实现目标

所以为了减轻开发人员的负担,我打算这样做:

所有操作统一API,将API层抽象出来,每个平台去实现API抽象接口,开发人员只需要注入接口,自动根据参数寻找对应的实现类。

对,你没看错,开发人员只需要@Autowired 接口

例如:获取直播地址,开发人员只需要关注接口就行了

6.实现思路

如果开发人员只关注接口,那么一个接口有多个实现类啊(多个厂商平台就是多个实现类),

spring接口注入有多个实现类会报错啊,并且我要实现调用抽象API的方法时才知道是哪个实现类啊,也就是动态查找是哪个平台的实现类,所以不可能一开始就知道是找哪个实现类。

这时候代理模式就派上用场了。

我们让每个抽象接口注入代理类(动态代理),代理类再去寻找符合条件的实现类,这是第一点

第二点这么多抽象接口需要为每个抽象接口生成1个代理类,什么时候生成?

代理类注入流程:

代理类生成部分截图

第三点代理类怎么去寻找到符合条件的实现类,我们可以自定义1个平台注解,在实现类上打上注解,调用抽象API层的时候将平台标识传递过来就可以了啊,生成代理类的时候我们已经将注解和实现类建立了映射关系

第四点因为我们是动态代理,spring启动的时候如果用@Autowired 注解还是会报错,因为代理类是动态生成的,spring一开始不知道,所以我们需要使用@lazy注解进行延迟注入

第五点 每个厂商的识别监控设备唯一可能不一样,比如有可能是一个参数或者2个参数才能识别到唯一的监控设备进行操作,这时候我们只需要定义1个抽象的父类就行了

7.源码获取

以上就是全部思路,需要整个工程源码的加我私人微信 备注源码领取,有疑问也可以讨论一下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值