来自一个大佬的博客,建议食用

设计模式不分语言,是一种思维层面的体现,但是不能在不同语言中使用同一套实现(每种语言有不同的特性),比如go,本身是没有继承一说,但是通过结构体的组合来实现语义上的继承。而多态也是通过接口的方式来实现的。

下方的图来自于大佬博客,贴在这里方便查看!!!

设计原则

设计模式

结构型模式

代理模式

首先,我们知道代理模式中分为静态代理和动态代理。静态代理需要在编译前就要写好,而动态代理需要在运行时通过反射来实现方法增强。
上述的话,太过粗糙,下面列举一下双方的区别:

静态代理:

  • 代理类实现和目标类相同的接口,每个类都单独编辑一个代理类。
  • 我们需要在代理类中,将目标类中的所有方法都要重新实现,并且为每个方法都附加相似的代码逻辑。
  • 如果要添加方法增强的类不止一个,我们需要对每个类都创建一个代理类。

动态代理:

  • 不需要为每个目标类编辑代理类。
  • 在程序运行时,系统会动态地创建代理类,然后用代理类替换掉原始类。
  • 一般采用反射实现。

代理模式的优点:

  • 代理模式能将代理对象与真实被调用目标对象分离。
  • 在一定程度上降低了系统的耦合性,拓展性好。
  • 可以起到保护目标对象的作用。
  • 可以增强目标对象的功能。

代理的应用场景:

  • 监控
  • 统计
  • 鉴权
  • 限流
  • 事务

静态代理

这里很好看懂,不需过多赘述。

import ("fmt""time"
)//静态代理
//就是对目标类提前实现一个代理类,在调用时使用代理类即可
//代理时需要实现目标类的全部方法type IUser interface {Login(username, password string) error
}type User struct {}func (u *User) Login(username, password string) error {//这里就是目标类的函数处理逻辑return nil
}//接下来是代理上述User结构体
type UserProxy struct {//有点挟天子以令诸侯,哈哈哈,开个玩笑user *User
}func NewUserProxy(user *User) *UserProxy {//返回静态代理类return &UserProxy{user: user,}
}func (p *UserProxy) Login(username, password string) error {//这里就代理一个程序消耗计时功能start := time.Now()err := p.user.Login(username, password)if err != nil {return err}//其实这里用defer栈也可以fmt.Printf("调用该程序用时:%v",time.Since(start))return nil
}

动态代理

思路:仿照java动态代理的思路,通过InvocationHandler来提供Invoke接口,然后用Proxy结合接口去生成代理类,这个接口需要用户自己实现自有逻辑。

//提供动态调用方法接口
type InvocationHandler interface {Invoke(proxy *Proxy, method *Method, args []interface{}) ([]interface{}, error)
}//代理,用来总管代理类的生成
type Proxy struct {target  interface{}        //目标类,后面的类型和java的Object一样methods map[string]*Method //map用来装载待增强的不同的方法handle  InvocationHandler  //用来暴露统一invoke接口,类似多态
}//创建新的代理
func NewProxy(target interface{}, h InvocationHandler) *Proxy {typ := reflect.TypeOf(target)          //用来显示目标类动态的真实类型value := reflect.ValueOf(target)       //获取目标类的值methods := make(map[string]*Method, 0) //初始化目标类的方法map//将目标类的方法逐个装载for i := 0; i < value.NumMethod(); i++ {method := value.Method(i)methods[typ.Method(i).Name] = &Method{value: method}}return &Proxy{target: target, methods: methods, handle: h}
}//代理调用代理方法
func (p *Proxy) InvokeMethod(name string, args ...interface{}) ([]interface{}, error) {return p.handle.Invoke(p, p.methods[name], args)
}//用来承载目标类的方法定位和调用
type Method struct {value reflect.Value //用来装载方法实例
}//这里相当于调用原方法,在该方法外可以做方法增强,需要调用者自己实现!!!
func (m *Method) Invoke(args ...interface{}) (res []interface{}, err error) {defer func() {//用来捕捉异常if p := recover(); p != nil {err = errors.New(fmt.Sprintf("%s", p))}}()//处理参数params := make([]reflect.Value, 0)if args != nil {for i := 0; i < len(args); i++ {params = append(params, reflect.ValueOf(args[i]))}}//调用方法call := m.value.Call(params)//接收返回值res = make([]interface{}, 0)if call != nil && len(call) > 0 {for i := 0; i < len(call); i++ {res = append(res, call[i].Interface())}}return
}

测试代码:

func TestMethod_Invoke(t *testing.T) {//这里对活动时长做统计people := &People{}   //创建目标类h := new(PeopleProxy) //创建接口实现类proxy := NewProxy(people, h)//调用方法ret, err := proxy.InvokeMethod("Work", "打游戏", "学习")if err != nil {fmt.Println(err)}fmt.Println(ret)
}//目标类
type People struct {}func (p *People) Work(content string, next string) string {fmt.Println("活动内容是:" + content + ",接下来需要做:" + next)return "all right"
}//用户需要自己实现的增强内容,需要实现InvocationHandler接口
type PeopleProxy struct {}//在这里做方法增强
func (p *PeopleProxy) Invoke(proxy *Proxy, method *Method, args []interface{}) ([]interface{}, error) {start := time.Now()defer fmt.Printf("耗时:%v\n", time.Since(start))fmt.Println("before method")invoke, err := method.Invoke(args...)fmt.Println("after method")return invoke, err
}

浅谈golang中的代理模式相关推荐

  1. 浅谈开发中的MVVM模式及与MVP和MVC的区别

    2019独角兽企业重金招聘Python工程师标准>>> 我记得前段时间分享了一篇文章< 浅谈Andorid开发中的MVP模式>(点击可跳转),反响不错,为了进一步介绍MV ...

  2. 浅谈java的静态代理模式

    嗨喽-小伙伴们XX好呀, 本章我们来介绍,java中出现的静态代理模式. 代理,对应于英语单词-----Proxy,从字面上理解,就是在实现代理目标(Target)所有的需求的同时,还能够实现代理目标 ...

  3. 浅谈自己对Java代理模式的理解--即为什么要用怎么用

    首先,国际惯例,上Java代理模式的定义:  Java代理模式:对其他对象提供一种代理以控制对这个对象的访问.              定义很简单,就一句话,怎么去理解,不急,先听一个小故事: 故事 ...

  4. 浅谈安卓中的MVP模式

    端午放假,天气下雨,于是乎在家撸一下博客,本篇博客将为大家解析MVP模式在安卓中的应用. 本文将从以下几个方面对MVP模式进行讲解: 1.  MVP简介 2.  为什么使用MVP模式 3.  MVP模 ...

  5. 浅谈Android中的MVP与动态代理的结合

    浅谈Android中的MVP与动态代理的结合 本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 在Android开发平台上接触MVP足足算起来大概已经有一个年头左右.从最开始到现在经 ...

  6. 理解各种设计模式原则及区别丨浅谈Nginx中核心设计模式-责任链模式丨C++后端开发丨Linux服务器开发丨web服务器

    理解各种设计模式原则及区别丨浅谈Nginx中核心设计模式-责任链模式 1. 开闭.单一职责.里氏替换.接口隔离等设计原则 2. 随处可见的模板方法 3. nginx中核心设计模式 责任链模式 4. 责 ...

  7. 浅谈caffe中train_val.prototxt和deploy.prototxt文件的区别

    浅谈caffe中train_val.prototxt和deploy.prototxt文件的区别 标签: caffe深度学习CaffeNet 2016-11-02 16:10 1203人阅读 评论(1) ...

  8. python的re2和re区别_浅谈Python中re.match()和re.search()的使用及区别

    1.re.match()fvk免费资源网 re.match()的概念是从头匹配一个符合规则的字符串,从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None.fvk免费资源网 包含的参数如下: ...

  9. 浅谈Hibernate中的几个查询

    浅谈Hibernate中的几个查询 一.load和get方法的区别 1.load在查询时,先从一级缓存中寻找与数据索引对应的实体对象,然后构建并返回一个代理对象,当我们真正使用这个代理对象的时候,这时 ...

最新文章

  1. spring bean xml 调用方法_Spring通过Xml方式注册Bean的几处关键实现点
  2. 【Linux】一步一步学Linux——telinit命令(144)
  3. [Java基础]Set集合概述和特点
  4. python变量如何用循环定义_Python学习日记1(变量定义,分支,循环)
  5. [转]把人当成一个公司来经营,心就不会那么累
  6. python scapy sniffer停止抓包_如果没有收到数据包,如何告诉scapy sniff()停止?
  7. python, 面向对象编程Object Oriented Programming(OOP)
  8. php 绘图 jpeg,PHP gd库增加jpeg支持
  9. Apache Pulsar的多租户消息系统
  10. 游戏设计阻力探秘之扩展空间
  11. 实例学习ZMODEM文件传输协议
  12. linux memtest错误但没死机,LINUX系统无故死机,系统日志报错如下,各位帮忙看看是因为什么...
  13. hive建表语句 增加字段、分区基础操作
  14. 关于GomezPeer赚钱的可行性调查
  15. 查找恶意的TOR中继节点
  16. 给大家安利一个Python版本的记忆翻牌小游戏!上才艺!!
  17. 一分钟快速把一篇论文后面的参考文献全部下载下来
  18. 计算机应用基础全解,第三章习题-ddg全解.doc
  19. ubuntu20.04离线安装python2.7.17
  20. 怎样修改图纸中单个图块的基点 ?

热门文章

  1. 【Vue】组件间传值的三种方式:父传子,子传父,非父子传值
  2. 淘宝商品数据清洗及预处理
  3. 怎么计算机会成本,机会成本计算公式,实例解读机会成本
  4. jquery 堆栈溢出_带有jQuery和CSS3的漂亮照片堆栈库
  5. 中国股市最“暴利”时代,而有的人活在15年的熊市!
  6. 公用Foot和友情链接模块代码模板
  7. Python学习 Day31 DOM
  8. 7-1 计算π的值 (10分) java
  9. 怎么修改计算机密码界面的背景,操作方法:在Win10中输入密码时如何修改登录界面的背景图片(两种方法)...
  10. doom3 源代码评测 1