结构型之代理模式
百里守约学编程 于 2022-09-20 23:48:12 发布 87 收藏
分类专栏: # go设计模式 文章标签: 代理模式 golang 设计模式
12 篇文章 0 订阅
package proxy

import (
	"log"
	"time"
)

// IUser IUser
type IUser interface {
	Login(username, password string) error
}

// User 用户
type User struct {
}

// Login 用户登录
func (u *User) Login(username, password string) error {
	// 不实现细节
	return nil
}

// UserProxy 代理类,包含了原始类,并且和原始类实现了相同接口IUser
type UserProxy struct {
	user *User
}

// NewUserProxy NewUserProxy
func NewUserProxy(user *User) *UserProxy {
	return &UserProxy{
		user: user,
	}
}

// Login 登录,和 user 实现相同的接口
func (p *UserProxy) Login(username, password string) error {
	// before 这里可能会有一些统计的逻辑
	start := time.Now()

	// 这里是原有的业务逻辑
	if err := p.user.Login(username, password); err != nil {
		return err
	}

	// after 这里可能也有一些监控统计的逻辑
	log.Printf("user login cost time: %s", time.Now().Sub(start))

	return nil
}
// 代理模式:代理模式在不改变原始类接口的条件下,为原始类定义一个代理类,主要目的是控制访问,而非加强功能,这是它跟装饰器模式最大的不同。
package main

// 场景举例:为 UserController 的 register 和 login 方法增加 metrics 打点

// 用户类,业务中用到的实体类
type UserVo struct{}

// 抽象接口,在业务代码中使用接口
type IUserController interface {
	login(telephone, password string) UserVo
	register(telephone, password string) UserVo
}

// UserController 类,被代理类,处理实际业务
type UserController struct{}

func (uc UserController) register(telephone, password string) UserVo {
	// ... register 逻辑 ...
	return UserVo{}
}

func (uc UserController) login(telephone, password string) UserVo {
	// ... login 逻辑 ...
	return UserVo{}
}

// metrics 类
type MetricsCollector struct{}

func (ms MetricsCollector) recordRequest() {}

func NewMetricsCollector() MetricsCollector {
	return MetricsCollector{}
}

// UserController的代理类,组合其他类对UserController类相关功能增强
type UserControllerProxy struct {
	userController   UserController
	metricsCollector MetricsCollector
}

func NewUserControllerProxy(userController UserController) UserControllerProxy {
	return UserControllerProxy{
		userController:   userController,
		metricsCollector: NewMetricsCollector(),
	}
}

// 需要和被代理类实现相同接口,这样才可以把代理类传给接口,然后使用接口,感觉上就像和在使用被代理类一样,实际已经对功能进行了增强
func (ucp UserControllerProxy) register(telephone, password string) UserVo {
	userVo := ucp.userController.register(telephone, password)
	ucp.metricsCollector.recordRequest()
	return userVo
}

func (ucp UserControllerProxy) login(telephone, password string) UserVo {
	userVo := ucp.userController.login(telephone, password)
	ucp.metricsCollector.recordRequest()
	return userVo
}