生命不息,学习不止
- 事件系统原理
- 事件注册实现
- 事件调用实现
- 处理方实现
- 事件触发
- 你以为结束了
话说这是一个风和日丽的上午,拿到了外卖小哥送来的我最心爱的麻辣烫,我打开了因为昨天刚充了三毛钱电费而恢复了使用的电脑,登上了满是美女好友的微信,熟悉的声音马上响彻在了我这三百平米的卧室中,果然我的魅力无法让人自拔,点开这闪烁的美女头像,一行文字映入眼帘,还钱,月底还不还钱把你麻辣烫到了…… 真好
话说最近各地都开始下雪了,都降温了,是真冷啊
跑题了……废话不多说,上货
事件系统原理
事件系统可以分为两部分,事件的发生部分和处理部分,就像某个明星发生了丑闻,就会有公关,法务等等部门马上响应并处理。
一个事件系统拥有如下特性:
1.能够实现事件的一方,可以根据事件 ID 或名字注册对应的事件。
2.事件发起者,会根据注册信息通知这些注册者。
3.一个事件可以有多个实现方响应。
事件注册实现
事件的发生就会通知对应的处理方,所以我们需要将事件与处理方连接起来,所以我们需要通过注册的方式将事件与处理方连接起来
//创建一个全局事件集,用map切片储存,时间名为key,处理方法为value
var nameOfEvent = make(map[string][]func(interface{}))// 注册事件,提供事件名和回调函数
func RegisterEvent(name string, callback func(interface{})) {// 通过名字查找事件列表list := nameOfEvent[name]// 在列表切片中添加函数list = append(list, callback)// 将修改的事件列表切片保存回去nameOfEvent[name] = list
}
1.首先创建一个全局事件集,用map切片储存,时间名为key,处理方法为value
2.注册事件,事件名和回调函数(处理方法)作为参数
因为一个事件可以有多个处理方,所以采用数组储存不同处理方
事件调用实现
// 调用事件
func CallEvent(name string, param interface{}) {// 通过名字找到事件列表list := nameOfEvent[name]// 遍历这个事件的所有回调for _, callback := range list {// 传入参数调用回调callback(param)}
}
1.通过时间名获取处理方
2.遍历处理方,将每个函数回调传入事件参数并调用,就会触发事件实现方的逻辑处理。
处理方实现
// 声明机构的结构体
type Actor struct {Aname string Bname string
}
// 为机构添加一个事件处理函数
func (actor *Actor) OnEvent(param interface{}) {fmt.Println(actor.Aname,param)
}
// 为机构添加另一个事件处理函数
func (actor *Actor) GlobalEvent(param interface{}) {fmt.Println(actor.Bname, param)
}// 为第三方机构添加另一个事件处理函数
func ThreeOnEvent(param interface{}) {fmt.Println("第三方", param)
}
1.首先声明机构和第三方,代表多个处理方
2.实现对应处理方法
事件触发
func main() {// 实例化机构actor := Actor{"法务","公关",}// 注册名为OnSkill的法务回调RegisterEvent("xxx出轨了", actor.OnEvent)// 注册名为OnSkill的公关回调RegisterEvent("xxx出轨了", actor.GlobalEvent)// 再次在OnSkill上注册第三方事件RegisterEvent("xxx出轨了", ThreeOnEvent)// 调用事件,所有注册的同名函数都会被调用CallEvent("xxx出轨了", "开始行动")
}
- 实例化机构,并为机构中各部门署名
2.注册事件
3.自动处理
你以为结束了
结果演示,角色和全局的事件会按注册顺序顺序地触发。
一般来说,事件系统不保证同一个事件实现方多个函数列表中的调用顺序,事件系统认为所有实现函数都是平等的。也就是说,无论例子中的 a.OnEvent 先注册,还是 GlobalEvent() 函数先注册,最终谁先被调用,都是无所谓的,开发者不应该去关注和要求保证调用的顺序。
一个完善的事件系统还会提供移除单个和所有事件的方法。
大家看完发现有什么错误,写在下面吧!跟我黑虎阿福比划比划!