代理模式
代理模式,没接触过的自己度娘下基本概念吧
本文讲下具体应用,并展示下实作中的样子
举例应用说明
代理模式的一个典型应用,就是 AOP模式
AOP模式
通常把程序分为框架层与逻辑层
它的主要特点:
- 把很多个代理对象组合进 1 个 Context 对象(应用程序上下文对象)
- Context 对象功能可以横向扩展(即组合更多的代理对象进去)
- 框架层修改 Context 对象实现,逻辑层代码可以不用做任何更改
- 框架层通过 Context 对象提供新特性
- 通过 Context 对象,框架层、逻辑层达成交互
通常的 SDK 框架,都会采用的模式。如 .Net 框架、Java Spring 框架 等等
下面实例分析下 AOP 模式。直接上代码
context.go
package common
import (
"context"
"math/rand"
)
// Context : 应用程序上下文
type Context struct {
Ctx context.Context // 常驻功能
Rand *rand.Rand // 常驻功能
Config *Config // 常驻功能
Log ILogger // 常驻功能
Node INode // 常驻功能
ServerForClient ITCPServer // 注册该字段相应接口,才会开启
ServerForIntranet ITCPServer // 注册该字段相应接口,才会开启
Login ILogin // 注册该字段相应接口,才会开启
}
代码分析:
- 上述定义了 1 个应用程序上下文类
- 从定义可以看出,提供了:
- golang 的上下文对象功能
- 随机数生成器
- 应用程序配置访问接口
- 日志功能接口
- 服务节点功能(包括自动接入服务器组、服务发现、服务消息传递等等)
- 1 个对客户端的 TCP 服务
- 1 个对服务器组内的 TCP 服务
- 1 个登陆服务器组的登陆模块接口
- 显然根据项目需求,还可以继续横向扩展 Context 内容
- 对于逻辑层程序来说,只需要知道如何使用这些功能,而不需要知道其实现细节
- 实例化多个 Context ,即可在同一个进程模拟多个应用对象(如果需要的话)
plugin.go
go 语言一种比较好的框架层、逻辑层分离的手段,就是使用插件
- 框架层, 应用程序 app
- 逻辑层, 插件
- 应用程序 app 实现基础公共的功能,并通过 Context 传递给插件
我们来看下插件类:
扫描二维码关注公众号,回复:
8631990 查看本文章
// 无关代码略
// Plugin : 插件组件
type Plugin struct {
ctx *common.Context
}
// NewPlugin : 实例化
func NewPlugin(ctx *common.Context) *Plugin {
return &Plugin{ctx: ctx}
}
// 无关代码略
func loadPlugin(ctx *common.Context) {
once0.Do(func() {
appName := viper.GetString("app")
if appName == "" {
printUsage()
os.Exit(1)
}
so, err := plugin.Open(appName + ".so")
if err != nil {
ctx.Log.Errorln(err)
os.Exit(1)
}
// 无关代码略
c, err := so.Lookup("Ctx")
if err != nil {
ctx.Log.Errorln(err)
os.Exit(1)
}
// 无关代码略
*c.(**common.Context) = ctx
})
}
代码分析:
- 上面代码中,省略了,无关代码,方便分析
- 框架层在加载逻辑插件时,把 ctx 对象(应用程序上下文)传递给逻辑层
main.go
package main
import (
"fmt"
"github.com/fananchong/go-xserver/common"
)
// PluginObj : 代表一个插件对象
var PluginObj common.Plugin
// PluginType : 插件类型
var PluginType common.NodeType
// Ctx : 应用程序上下文
var Ctx *common.Context
var login = NewLogin()
func init() {
fmt.Println("LOAD PLUGIN: LOGIN")
PluginObj = &Plugin{}
PluginType = common.Login
}
// Plugin : 插件类
type Plugin struct {
}
// Start : 插件类实现启动
func (plugin *Plugin) Start() bool {
Ctx.Log.Infoln("Plugin Start")
login.Start()
return true
}
// Close : 插件类实现关闭
func (plugin *Plugin) Close() {
Ctx.Log.Infoln("Plugin Close")
login.Close()
}
// main : 作为插件包,该函数可以不存在。添加之,是避免 go-lint 烦人的错误提示
func main() {}
代码分析:
- 这里分析下登陆服的逻辑插件
var Ctx *common.Context
应用程序上下文对象,必须定义。框架层加载插件时,会 lookup ,并设置它Ctx.Log.Infoln
直接通过 Context 对象,来使用框架层的日志功能
更多细节
更多细节请参考:
欢迎 Star & Fork