大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺
设计模式不分语言,是一种思维层面的体现,但是不能在不同语言中使用同一套实现(每种语言有不同的特性),比如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
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/159492.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...