1. 目的
使用观察者模式降低模块间的耦合性
2. 主要思路
- 通过C# 的 Dictionary 存放事件码和事件的委托
- 添加事件:
- 判断字典是否有该事件码,没有添加
- 判断当前委托类型与添加的事件码的类型是否一致
- 最后订阅该事件
- 移除事件:
- 先判断事件码是否存在
- 取消订阅
- 最后判断事件码是否为空,是null则移除事件码
- 广播事件:
- 若事件委托不为null,广播事件
3. 基础类
- SingletonBase 单例模式基类
/*
* FileName: SingletonBase
* Author: ming
* CreateTime: 2023/6/28 11:46:00
* Description: 单例模式基类
*
*/
using UnityEngine;
using System.Collections;
public class SingletonBase<T> where T : new() {
private static T _Instance;
public static T GetInstance()
{
if (_Instance == null) _Instance = new T();
return _Instance;
}
}
- EventEnum 事件枚举类
public enum EventEnum
{
}
- CallBack 委托类
/*
* FileName: CallBack
* Author: ming
* CreateTime: 2023/6/28 14:22:38
* Description: 委托
*
*/
// 无参委托
public delegate void CallBack();
// 带参委托
public delegate void CallBack<T>(T arg);
public delegate void CallBack<T, X>(T arg1, X arg2);
public delegate void CallBack<T, X, Y>(T arg1, X arg2, Y arg3);
public delegate void CallBack<T, X, Y, Z>(T arg1, X arg2, Y arg3, Z arg4);
public delegate void CallBack<T, X, Y, Z, W>(T arg1, X arg2, Y arg3, Z arg4, W arg5);
4. EventCenter 事件中心类
/*
* FileName: EventCenter
* Author: ming
* CreateTime: 2023/6/28 14:15:39
* Description: 事件中心类,添加、删除、分发事件
*
*/
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
public class EventCenter : MonoBehaviour
{
// 字典,用于存放事件码和委托对应
private static Dictionary<EventEnum, Delegate> m_EventTable = new Dictionary<EventEnum, Delegate>();
#region 添加和移除事件前的判断
// 添加事件监听前的判断
private static void OnAddListenerJudge(EventEnum eventEnum, Delegate callBack) {
// 先判断事件码是否存在于字典中,不存在则先添加
if (!m_EventTable.ContainsKey(eventEnum)) {
// 先给字典添加事件码,委托设置为空
m_EventTable.Add(eventEnum, null);
}
// 判断当前事件码的委托类型和要添加的委托类型是否一致,不一致不能添加,抛出异常
Delegate d = m_EventTable[eventEnum];
if (d != null && d.GetType() != callBack.GetType()) {
throw new Exception(string.Format("尝试为事件码{0}添加不同事件的委托,当前事件所对应的委托是{1},要添加的委托类型{2}", eventEnum, d.GetType(), callBack.GetType()));
}
}
// 移除事件码前的判断
private static void OnRemoveListenerBeforeJudge(EventEnum eventEnum) {
// 判断是否包含指定事件码
if (!m_EventTable.ContainsKey(eventEnum)) {
throw new Exception(string.Format("移除监听错误;没有事件码", eventEnum));
}
}
// 移除事件码后的判断,用于移除字典中空的事件码
private static void OnRemoveListenerLaterJudge(EventEnum eventEnum) {
if (m_EventTable[eventEnum] == null) {
m_EventTable.Remove(eventEnum);
}
}
#endregion
#region 添加监听
// 无参
public static void AddListener(EventEnum eventEnum, CallBack callBack) {
OnAddListenerJudge(eventEnum, callBack);
m_EventTable[eventEnum] = (CallBack)m_EventTable[eventEnum] + callBack;
}
// 带参数
public static void AddListener<T>(EventEnum eventEnum, CallBack<T> callBack) {
OnAddListenerJudge(eventEnum, callBack);
m_EventTable[eventEnum] = (CallBack<T>)m_EventTable[eventEnum] + callBack;
}
public static void AddListener<T, X>(EventEnum eventEnum, CallBack<T, X> callBack) {
OnAddListenerJudge(eventEnum, callBack);
m_EventTable[eventEnum] = (CallBack<T, X>)m_EventTable[eventEnum] + callBack;
}
public static void AddListener<T, X, Y>(EventEnum eventEnum, CallBack<T, X, Y> callBack) {
OnAddListenerJudge(eventEnum, callBack);
m_EventTable[eventEnum] = (CallBack<T, X, Y>)m_EventTable[eventEnum] + callBack;
}
public static void AddListener<T, X, Y, Z>(EventEnum eventEnum, CallBack<T, X, Y, Z> callBack) {
OnAddListenerJudge(eventEnum, callBack);
m_EventTable[eventEnum] = (CallBack<T, X, Y, Z>)m_EventTable[eventEnum] + callBack;
}
public static void AddListener<T, X, Y, Z, W>(EventEnum eventEnum, CallBack<T, X, Y, Z, W> callBack) {
OnAddListenerJudge(eventEnum, callBack);
m_EventTable[eventEnum] = (CallBack<T, X, Y, Z, W>)m_EventTable[eventEnum] + callBack;
}
#endregion
#region 移除监听
public static void RemoveListener(EventEnum eventEnum, CallBack callBack) {
OnRemoveListenerBeforeJudge(eventEnum);
m_EventTable[eventEnum] = (CallBack)m_EventTable[eventEnum] - callBack;
OnRemoveListenerLaterJudge(eventEnum);
}
public static void RemoveListener<T>(EventEnum eventEnum, CallBack<T> callBack) {
OnRemoveListenerBeforeJudge(eventEnum);
m_EventTable[eventEnum] = (CallBack<T>)m_EventTable[eventEnum] - callBack;
OnRemoveListenerLaterJudge(eventEnum);
}
public static void RemoveListener<T, X>(EventEnum eventEnum, CallBack<T, X> callBack) {
OnRemoveListenerBeforeJudge(eventEnum);
m_EventTable[eventEnum] = (CallBack<T, X>)m_EventTable[eventEnum] - callBack;
OnRemoveListenerLaterJudge(eventEnum);
}
public static void RemoveListener<T, X, Y>(EventEnum eventEnum, CallBack<T, X, Y> callBack) {
OnRemoveListenerBeforeJudge(eventEnum);
m_EventTable[eventEnum] = (CallBack<T, X, Y>)m_EventTable[eventEnum] - callBack;
OnRemoveListenerLaterJudge(eventEnum);
}
public static void RemoveListener<T, X, Y, Z>(EventEnum eventEnum, CallBack<T, X, Y, Z> callBack) {
OnRemoveListenerBeforeJudge(eventEnum);
m_EventTable[eventEnum] = (CallBack<T, X, Y, Z>)m_EventTable[eventEnum] - callBack;
OnRemoveListenerLaterJudge(eventEnum);
}
public static void RemoveListener<T, X, Y, Z, W>(EventEnum eventEnum, CallBack<T, X, Y, Z, W> callBack) {
OnRemoveListenerBeforeJudge(eventEnum);
m_EventTable[eventEnum] = (CallBack<T, X, Y, Z, W>)m_EventTable[eventEnum] - callBack;
OnRemoveListenerLaterJudge(eventEnum);
}
#endregion
#region 广播事件
public static void Broadcast(EventEnum eventEnum) {
Delegate d;
if (m_EventTable.TryGetValue(eventEnum, out d)) {
CallBack callBack = d as CallBack;
if (callBack != null) {
callBack();
}
}
}
public static void Broadcast<T>(EventEnum eventEnum, T arg1) {
Delegate d;
if (m_EventTable.TryGetValue(eventEnum, out d)) {
CallBack<T> callBack = d as CallBack<T>;
if (callBack != null) {
callBack(arg1);
}
}
}
public static void Broadcast<T, X>(EventEnum eventEnum, T arg1, X arg2) {
Delegate d;
if (m_EventTable.TryGetValue(eventEnum, out d)) {
CallBack<T, X> callBack = d as CallBack<T, X>;
if (callBack != null) {
callBack(arg1, arg2);
}
}
}
public static void Broadcast<T, X, Y>(EventEnum eventEnum, T arg1, X arg2, Y arg3) {
Delegate d;
if (m_EventTable.TryGetValue(eventEnum, out d)) {
CallBack<T, X, Y> callBack = d as CallBack<T, X, Y>;
if (callBack != null) {
callBack(arg1, arg2, arg3);
}
}
}
public static void Broadcast<T, X, Y, Z>(EventEnum eventEnum, T arg1, X arg2, Y arg3, Z arg4) {
Delegate d;
if (m_EventTable.TryGetValue(eventEnum, out d)) {
CallBack<T, X, Y, Z> callBack = d as CallBack<T, X, Y, Z>;
if (callBack != null) {
callBack(arg1, arg2, arg3, arg4);
}
}
}
public static void Broadcast<T, X, Y, Z, W>(EventEnum eventEnum, T arg1, X arg2, Y arg3, Z arg4, W arg5) {
Delegate d;
if (m_EventTable.TryGetValue(eventEnum, out d)) {
CallBack<T, X, Y, Z, W> callBack = d as CallBack<T, X, Y, Z, W>;
if (callBack != null) {
callBack(arg1, arg2, arg3, arg4, arg5);
}
}
}
#endregion
}
5. 测试
创建场景:
BtnClick:文章来源:https://www.toymoban.com/news/detail-517405.html
/*
* FileName: BtnClick
* Author: ming
* CreateTime: 2023/6/28 17:41:23
* Description:
*
*/
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class BtnClick : MonoBehaviour
{
private Button noParameter;
private Button oneParameter;
private Button twoParameter;
private Button threeParameter;
private Button fourParameter;
private Button fiveParameter;
void Awake()
{
noParameter = transform.Find("NoParameter").GetComponent<Button>();
oneParameter = transform.Find("OneParameter").GetComponent<Button>();
twoParameter = transform.Find("TwoParameter").GetComponent<Button>();
threeParameter = transform.Find("ThreeParameter").GetComponent<Button>();
fourParameter = transform.Find("FourParameter").GetComponent<Button>();
fiveParameter = transform.Find("FiveParameter").GetComponent<Button>();
}
void Start()
{
noParameter.onClick.AddListener(() => {
EventCenter.Broadcast(EventEnum.ShowText0);
});
oneParameter.onClick.AddListener(() => {
EventCenter.Broadcast(EventEnum.ShowText1, "hello world!!!");
});
twoParameter.onClick.AddListener(() => {
EventCenter.Broadcast(EventEnum.ShowText2, "hello world!!!", 2.0f);
});
threeParameter.onClick.AddListener(() =>
{
EventCenter.Broadcast(EventEnum.ShowText3, "hello world!!!", 2.0f, 3);
});
fourParameter.onClick.AddListener(() =>
{
EventCenter.Broadcast(EventEnum.ShowText4, "hello world!!!", 2.0f, 3, "ming");
});
fiveParameter.onClick.AddListener(() =>
{
EventCenter.Broadcast(EventEnum.ShowText5, "hello world!!!", 2.0f, 3, "ming", 5);
});
}
}
ShowText:文章来源地址https://www.toymoban.com/news/detail-517405.html
/*
* FileName: ShowText
* Author: ming
* CreateTime: 2023/6/28 18:07:46
* Description:
*
*/
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class ShowText : MonoBehaviour
{
void Awake()
{
gameObject.SetActive(false);
EventCenter.AddListener(EventEnum.ShowText0, ShowText0);
EventCenter.AddListener<string>(EventEnum.ShowText1, ShowText1);
EventCenter.AddListener<string, float>(EventEnum.ShowText2, ShowText2);
EventCenter.AddListener<string, float, int>(EventEnum.ShowText3, ShowText3);
EventCenter.AddListener<string, float, int, string>(EventEnum.ShowText4, ShowText4);
EventCenter.AddListener<string, float, int, string, int>(EventEnum.ShowText5, ShowText5);
}
void OnDestroy()
{
EventCenter.RemoveListener(EventEnum.ShowText0, ShowText0);
EventCenter.RemoveListener<string>(EventEnum.ShowText1, ShowText1);
EventCenter.RemoveListener<string, float>(EventEnum.ShowText2, ShowText2);
EventCenter.RemoveListener<string, float, int>(EventEnum.ShowText3, ShowText3);
EventCenter.RemoveListener<string, float, int, string>(EventEnum.ShowText4, ShowText4);
EventCenter.RemoveListener<string, float, int, string, int>(EventEnum.ShowText5, ShowText5);
}
void ShowText0()
{
gameObject.SetActive(true);
transform.GetComponent<Text>().text = "noParameter";
}
void ShowText1(string str)
{
gameObject.SetActive(true);
transform.GetComponent<Text>().text = str;
}
void ShowText2(string str, float a)
{
gameObject.SetActive(true);
transform.GetComponent<Text>().text = str + a;
}
public void ShowText3(string str, float a, int b)
{
gameObject.SetActive(true);
GetComponent<Text>().text = str + a + b;
}
public void ShowText4(string str, float a, int b, string str2)
{
gameObject.SetActive(true);
GetComponent<Text>().text = str + a + b + str2;
}
public void ShowText5(string str, float a, int b, string str2, int c)
{
gameObject.SetActive(true);
GetComponent<Text>().text = str + a + b + str2 + c;
}
}
到了这里,关于Unity 事件监听与广播(高度解耦合,观察者模式)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!