微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Go设计模式(11)-代理模式

前面通过5篇文章讲解了创建型模式,创建型模式主要解决对象的创建问题,封装复杂的创建过程,解耦对象的创建代码和使用代码

  1. Go设计模式(6)-单例模式:用于创建全局唯一对象

  2. Go设计模式(7)-工厂模式:用于根据参数,创建不同但是相关类型的对象

  3. Go设计模式(8)-抽象工厂:用于创建对象时,减少工厂类个数,增加可维护性

  4. Go设计模式(9)-建造者模式:用于创建复杂对象

  5. 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,但是还要做很多琐碎、通用的工作,如校验签名、初始化订单数据、参数检查、记录日志等。这些琐碎功能如果让每一个支付类自己处理,不但是重复开发,而且后期修改时不易维护,这时候就很适合用代理模式。

图片

  1. 框架设计,如RPC的实现。调用RPC客户端,客户端会自动调用RPC服务端,客户端也是一个代理,做了大量操作让开发者可以不关心是如何成功调用到服务端的,只需要关心逻辑实现即可。

3.代码实现

这里简单实现一下支付网关发起支付功能是如何使用代理模式的。

package main

import (
   "fmt"
)

/**
 * @Description: 支付接口,只包含发起支付功能
 */
type PaymentService interface {
   pay(order string) string
}

/**
 * @Description: 微信支付类
 */
type WXPay struct {
}

/**
 * @Description: 微信支付类,从微信获取支付token
 * @receiver w
 * @param order
 * @return string
 */
func (w *WXPay) pay(order string) string {
   return "从微信获取支付token"
}

/**
 * @Description: 阿里支付类
 */
type AliPay struct {
}

/**
 * @Description: 阿里支付类,从阿里获取支付token
 * @receiver a
 * @param order
 * @return string
 */
func (a *AliPay) pay(order string) string {
   return "从阿里获取支付token"
}

/**
 * @Description: 支付代理类
 */
type PaymentProxy struct {
   realPay PaymentService
}

/**
 * @Description: 做校验签名、初始化订单数据、参数检查、记录日志、组装这种通用性操作,调用真正支付类获取token
 * @receiver p
 * @param order
 * @return string
 */
func (p *PaymentProxy) pay(order string) string {
   fmt.Println("处理" + order)
   fmt.Println("1校验签名")
   fmt.Println("2格式化订单数据")
   fmt.Println("3参数检查")
   fmt.Println("4记录请求日志")
   token := p.realPay.pay(order)
   return "http://组装" + token + "然后跳转到第三方支付"
}
func main() {
   proxy := &PaymentProxy{
      realPay: &AliPay{},
   }
   url := proxy.pay("阿里订单")
   fmt.Println(url)
}

输出为:

➜ myproject go run main.go

处理阿里订单

1校验签名

2格式化订单数据

3参数检查

4记录请求日志

http://组装从阿里获取支付token然后跳转到第三方支付

代码比较简单,但效果还是很好的,大家可以思考一下,如果再使用上Go设计模式(7)-工厂模式,是不是就全自动化了,今后接入新的第三方支付,只需要开发新的支付类,框架上几乎不需要修改,研发和测试的成本会降低很多。这也解释了设计模式的妙用。

总结

代理模式简单实用,使用得当能让系统可扩展性增强。它能帮助开发者实现具体业务和通用逻辑的分离,是开发者只需关注具体业务,满足开放-封闭、里氏替换、依赖倒转等原则。

最后

大家如果喜欢我的文章,可以关注我的公众号(程序员麻辣烫)

我的个人博客为:https://shidawuhen.github.io/

图片

往期文章回顾:

招聘

  1. 字节跳动|今日头条广州服务端研发工程师内推

  2. 字节跳动|抖音电商急招上海前端开发工程

  3. 字节跳动|抖音电商上海资深服务端开发工程师-交易

  4. 字节跳动|抖音电商武汉服务端(高级)开发工程师

  5. 字节跳动|飞书大客户产品经理内推咯

  6. 字节跳动|抖音电商服务端技术岗位虚位以待

  7. 字节跳动招聘专题

设计模式

  1. Go设计模式(10)-原型模式

  2. Go设计模式(9)-建造者模式

  3. Go设计模式(8)-抽象工厂

  4. Go设计模式(7)-工厂模式

  5. Go设计模式(6)-单例模式

  6. Go设计模式(5)-类图符号表示法

  7. Go设计模式(4)-代码编写优化

  8. Go设计模式(4)-代码编写

  9. Go设计模式(3)-设计原则

  10. Go设计模式(2)-面向对象分析与设计

  11. Go设计模式(1)-语法

语言

  1. 一文搞懂pprof

  2. Go工具之generate

  3. Go单例实现方案

  4. Go通道实现原理

  5. Go定时器实现原理

  6. Beego框架使用

  7. Golang源码BUG追查

  8. Gin框架简洁版

  9. Gin源码剖析

架构

  1. 支付接入常规问题

  2. 限流实现2

  3. 秒杀系统

  4. 分布式系统与一致性协议

  5. 微服务之服务框架和注册中心

  6. 浅谈微服务

  7. 限流实现1

  8. CDN请求过程详解

  9. 常用缓存技巧

  10. 如何高效对接第三方支付

  11. 算法总结

存储

  1. MySQL开发规范

  2. Redis实现分布式锁

  3. 事务原子性、一致性、持久性的实现原理

  4. InnoDB锁与事务简析

网络

  1. HTTP2.0基础教程

  2. HTTPS配置实战

  3. HTTPS连接过程

  4. TCP性能优化

工具

  1. GoLand实用技巧

  2. 根据mysql表自动生成go struct

  3. Markdown编辑器推荐-typora

读书笔记

  1. 《毛选》推荐

  2. 原则

  3. 资治通鉴

  4. 敏捷革命

  5. 如何锻炼自己的记忆力

  6. 简单的逻辑学-读后感

  7. 热风-读后感

  8. 论语-读后感

  9. 孙子兵法-读后感

思考

  1. 为动员一切力量争取胜利而斗争

  2. 反对自由主义

  3. 实践论

  4. 评价自己的标准

  5. 服务端团队假期值班方案

  6. 项目流程管理

  7. 对项目管理的一些看法

  8. 对产品经理的一些思考

  9. 关于程序员职业发展的思考

  10. 关于代码review的思考

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐