前面通过5篇文章讲解了创建型模式,创建型模式主要解决对象的创建问题,封装复杂的创建过程,解耦对象的创建代码和使用代码。
- Go设计模式(6)-单例模式:用于创建全局唯一对象
- Go设计模式(7)-工厂模式:用于根据参数,创建不同但是相关类型的对象
- Go设计模式(8)-抽象工厂:用于创建对象时,减少工厂类个数,增加可维护性
- Go设计模式(9)-建造者模式:用于创建复杂对象
- Go设计模式(10)-原型模式:用于创建成本较大的对象
从本篇文章开始讲解结构型模式,结构型模式主要总结了一些类或对象组合在一起的经典结构,这些经典的结构可以解决特定应用场景的问题。
代理模式能够在不改变原始类(或叫被代理类)代码的情况下,通过引入代理类来给原始类附加功能。一般代理类和被代理类有同一个父类。
本文UML类图链接为:https://www.processon.com/view/link/609b39d6f346fb5a37705da6
本文代码链接为:https://github.com/shidawuhen/asap/blob/master/controller/design/11proxy.go
1.定义
1.1代理模式
代理模式:为其他对象提供一种代理以控制对这个对象的访问。
UML类图:
1.2分析
看UML类图,可以看出代理类Proxy和被代理类RealSubject实现了相同接口Subject,代理类包含被代理类的引用。代理模式实现了在被代理类外面套了一层壳。虽然整体的设计和思想都很简单,但效果却很明显。首先在请求RealSubject的时候,必须经过Proxy,这样一些前置或者后置通用操作都可以放在Proxy中,扩展性和通用性都会加强。其次,因为Proxy和RealSubject各自实现了一部分功能,会使RealSubject更加关注自己的业务逻辑,起到很好的隔离效果。
2. 使用场景
使用代理模式的场景有以下这些:
1.业务系统的非功能性需求开发:如监控、统计、鉴权、限流、事务、幂等、日志等,这些和业务没有关系,所以可以放到Proxy中,RealSubject只关注功能性需求。
以前写过一篇文章如何高效对接第三方支付,公司对接了大量的第三方支付公司(PayU、PayTM、WX),这些公司发起支付的流程是一样的,核心是获取token,但是还要做很多琐碎、通用的工作,如校验签名、初始化订单数据、参数检查、记录日志等。这些琐碎功能如果让每一个支付类自己处理,不但是重复开发,而且后期修改时不易维护,这时候就很适合用代理模式。
2.框架设计,如RPC的实现。调用RPC客户端,客户端会自动调用RPC服务端,客户端也是一个代理,做了大量操作让开发者可以不关心是如何成功调用到服务端的,只需要关心逻辑实现即可。
3.代码实现
这里简单实现一下支付网关发起支付功能是如何使用代理模式的。
1 | package main |
输出为:
➜ myproject go run main.go
处理阿里订单
1校验签名
2格式化订单数据
3参数检查
4记录请求日志
http://组装从阿里获取支付token然后跳转到第三方支付
代码比较简单,但效果还是很好的,大家可以思考一下,如果再使用上Go设计模式(7)-工厂模式,是不是就全自动化了,今后接入新的第三方支付,只需要开发新的支付类,框架上几乎不需要修改,研发和测试的成本会降低很多。这也解释了设计模式的妙用。
总结
代理模式简单实用,使用得当能让系统可扩展性增强。它能帮助开发者实现具体业务和通用逻辑的分离,是开发者只需关注具体业务,满足开放-封闭、里氏替换、依赖倒转等原则。