什么是事件系统是实现事件的响应和处理
概念:
-
Go语言将类型的方法与普通函数视为一个概念--->调用者无须关心谁来支持调用,系统会自动处理是否调用普通函数或类型的方法
事件系统的基本原理
概念:
-
将事件派发者与事件处理者解耦
-
事件系统的基本原理
一个事件系统拥有的特性:
-
能够实现事件的一方,可以根据事件 ID 或名字注册对应的事件。
-
事件发起者,会根据注册信息通知这些注册者。
-
一个事件可以有多个实现方响应。
事件注册
功能描述:
-
为外部提供一个注册入口
-
注册入口传入注册的事件名称和对应事件名称的响应函数
-
将事件名称和响应函数关联并保存起来
代码示例:
package main
/*
实例化一个通过字符串映射函数切片的map--->输入字符串找到映射的函数
*/
var event = make(map[string][]func(interface{}))
/*
通过事件名(string)关联回调列表([]func(interface{})
同一个事件名称可能存在多个事件回调,因此使用回调列表保存。回调的函数声明为 func(interface{})。
*/
/*
注册事件:--->形参为
1、事件名
2、回调函数
提供给外部的通过事件名注册响应函数的入口。
*/
func RegisterEvent(name string, callBack func(interface{})) {
//事件的列表
list := event[name]
/*
通过事件名(name)进行查询,返回回调列表([]func(interface{})
*/
//在列表切片中添加函数
list = append(list, callBack)
/*
为同一个事件名称在已经注册的事件回调的列表中再添加一个回调函数
*/
//将修改的事件列表切片保存回去
event[name] = list
/*
将修改后的函数列表设置到 map 的对应事件名中
*/
}
事件调用
注意区分事件调用方和注册方:
-
事件调用方是事发现场,负责将事件和事件发生的参数通过事件系统派发出去,而不关心事件到底由谁处理
-
事件注册方通过事件系统注册应该响应哪些事件及如何使用回调函数处理这些事件。
代码示例:
package main
//调用事件
func CallEvent(name string, param interface{}) {
//找到事件map映射
list := event[name]
/*
通过注册事件回调的 event 和事件名字查询处理函数列表 list
*/
//遍历列表找到函数
for _, callback := range list {
/*
遍历这个事件列表,如果没有找到对应的事件,list 将是一个空切片
*/
//传入参数调用回调
callback(param)
}
}
使用事件系统
需求:
-
在 main() 函数中调用事件系统的 CallEvent 生成 OnSkill 事件
-
这个事件有两个处理函数,一个是角色的 OnEvent() 方法,还有一个是函数 GlobalEvent()
示例代码:
package main
import (
"fmt"
)
/*
添加一个结构体
*/
type Actor struct {
}
/*
为这个结构体添加一个事件处理函数
相当于类的内部方法
*/
func (print *Actor) onEvent(param interface{}) {
//打印内容
fmt.Println("actor event is:", param)
}
/*
定义一个全局事件
为全局事件响应函数。有时需要全局进行侦听或者处理一些事件,这里使用普通函数实现全局事件的处理。
*/
func GlobalEvent(param interface{}) {
fmt.Println("global event is:", param)
}
func main() {
//实例化结构体
ac := new(Actor)
//注册一个回调函数
RegisterEvent("OnSkill", ac.onEvent)
/*
注册一个 OnSkill 事件,实现代码由 ac 的 OnEvent 进行处理。也就是 Actor的OnEvent() 方法。
*/
//在注册的回调函数上在注册一个全局事件
RegisterEvent("Onskill", GlobalEvent)
/*
模拟同一个名称对应不同的回调函数的场景
注册一个 OnSkill 事件,实现代码由 GlobalEvent 进行处理
注册的是同一个名字的事件,但前面注册的事件不会被覆盖,而是被添加到事件系统中,关联 OnSkill 事件的函数列表中。
*/
//调用事件
CallEvent("OnSkill", 100)
/*
模拟处理事件,通过 CallEvent() 函数传入两个参数,第一个为事件名,第二个为处理函数的参数
*/
}
注意:
-
事件系统不保证同一个事件实现方多个函数列表中的调用顺序,事件系统认为所有实现函数都是平等的。
-
无论例子中的 ac.OnEvent 先注册,还是 GlobalEvent() 函数先注册,最终谁先被调用,都是无所谓的
-