基于IOC解决对象依赖问题
基于IOC解决对象依赖问题
ioc是一种软件设计原则,用来降低代码之间耦合度。如果没有ioc机制,多个模块调用会显得异常繁琐,而ioc是将控制权从程序代码中抽离,交给外部的容器或框架,从而实现依赖关系的动态置顶,增加程序的灵活性和可维护性,下面我的例子只是一个简单的以容器为基础实现的ioc注册。
store.go:
- IocContainer:负责注册ioc对象、初始化ioc对象操作
ackage ioc
import (
"fmt"
"gitee.com/dujie5416/vblog/apps/users/config"
"github.com/gin-gonic/gin"
)
//
// IocContainer
// @Description: 定义一个对象注册表
//
type IocContainer struct {
// 采用map来保证对象的注册关系
store map[string]IocObject
}
/*
* Init
* @Description: 负责初始化所有的对象,因为map是无序的,这里如果要控制初始化的顺序,可以替换成list
* @receiver c
* @return error
*/
func (c *IocContainer) Init() error {
fmt.Println(c.store)
config.LoadMysqlConfigFromToml("../etc/mysql.toml")
// 遍历所有单例对象,并对每个单例对象进行初始化操作
for _, obj := range c.store {
if err := obj.Init(); err != nil {
return err
}
}
return nil
}
/*
* Registry
* @Description: 将对象注册到ioc中
* @receiver c
* @param obj
*/
func (c *IocContainer) Registry(obj IocObject) {
c.store[obj.Name()] = obj
}
/*
* Get
* @Description: 获取ioc对象的名字
* @receiver c
* @param name
* @return any
*/
func (c *IocContainer) Get(name string) any {
return c.store[name]
}
//
// GinApiHandlers
// @Description: gin api的接口,用于注册路由
//
type GinApiHandlers interface {
RegisterRouter(r gin.IRouter)
}
/*
* RouteRegistry
* @Description: 将每个api handlers 的路由注册到root router中
* @receiver c
* @param router
*/
func (c *IocContainer) RouteRegistry(router gin.IRouter) {
fmt.Println(c.store)
// 找到被扩管的APIHandler
for _, obj := range c.store {
if api, ok := obj.(GinApiHandlers); ok {
api.RegisterRouter(router)
}
}
}
interface.go:定义Init()和Name()函数,注册进ioc对象必须实现该两种方法
package ioc
//
// IocObject
// @Description: 定义注册进来的对象的约束条件
//
type IocObject interface {
// 对象的初始化
Init() error
// 对象的名称
Name() string
}
controller.go:专门用于注入controller对象
package ioc
/*
* Controller
* @Description: 专门用于注册controller对象
* @return *IocContainer
*/
func Controller() *IocContainer {
return controllerContainer
}
//ioc注册表对象,全局只有一个
var controllerContainer = &IocContainer{
store: map[string]IocObject{},
}
api.go:专门注册api对象
package ioc
import "fmt"
/*
* ApiHandler
* @Description: 专门用于注册api handler对象
* @return *IocContainer
*/
func ApiHandler() *IocContainer {
return apiHandlerContainer
}
//ioc注册表对象,全局只有一个
var apiHandlerContainer = &IocContainer{
store: map[string]IocObject{},
}
func init() {
fmt.Println("这是apihand")
}
将对象注入到ioc:
package impl
import (
"gitee.com/dujie5416/vblog/apps/blog"
"gitee.com/dujie5416/vblog/apps/users/config"
"gitee.com/dujie5416/vblog/ioc"
"gorm.io/gorm"
)
/*
* init
* @Description: 将blog impl 对象注册到ioc管理
*/
func init() {
ioc.Controller().Registry(&BlogImpl{})
}
//
// BlogImpl
// @Description: 博客实现结构体
//
type BlogImpl struct {
db *gorm.DB
}
/*
* Init
* @Description: 实现ioc obj 接口
* @receiver b
* @return error
*/
func (b *BlogImpl) Init() error {
b.db = config.C().Mysql.GetMysqlConnect()
return nil
}
func (b *BlogImpl) Name() string {
return blog.AppName
}
根据name获取ioc对象的值:
package api
import (
"gitee.com/dujie5416/vblog/apps/blog"
"gitee.com/dujie5416/vblog/ioc"
)
func init() {
ioc.ApiHandler().Registry(&BlogApiHandler{})
}
type BlogApiHandler struct {
svc blog.Service
}
func (b *BlogApiHandler) Init() error {
b.svc = ioc.Controller().Get(blog.AppName).(blog.Service)
return nil
}
func (b *BlogApiHandler) Name() string {
return blog.AppName
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 J.のblog!
评论