事件的监听与广播,高度解耦合。
一些我自己的理解
delegate
可存储函数指针;它的一些特性像是类——例如需要实例化(使用
new
关键字),可以使用+=
符号直接添加函数委托;需要事先定义一个委托模板(限定传入参数,和返回参数类型)。
顺带一提,event
和delegate
用起来是一样的。都可以用像是+=
的符号添加委托,都像是函数一样被调用就会调用所有注册的委托。但有一个明显的使用区别:event,别的类只能订阅、取消订阅;public delegate成员变量,别的类可以调用或者覆盖delegate变量。
另外,event
的声明需要delegate
:
public delegate void MyValueChanged(object sender, EventArgs e);
public event MyValueChanged OnMyValueChanged;
简易例子
using System;//需要 System
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public delegate void CallBack();//需要有参数的直接在这加上需要的参数就可以实现参数广播。
public enum EventTypee//广播事件
{
test
}
public class EventCenter : MonoBehaviour
{
private static Dictionary<EventTypee, Delegate> dic = new Dictionary<EventTypee, Delegate>();
/// <summary>
/// 添加事件监听
/// </summary>
/// <param name="eventType"></param>
/// <param name="callBack"></param>
public static void AddListener(EventTypee eventTypee,CallBack callBack)
{
if (!dic.ContainsKey(eventTypee))
{
dic.Add(eventTypee, null);
}
//异常抛出
Delegate m = dic[eventTypee];
if (m != null && m.GetType() != callBack.GetType())
{
throw new Exception(string.Format("事件{0}为不同委托,对应为{1},添加类型为{2}", eventTypee, m.GetType(), callBack.GetType()));
}
dic[eventTypee] = (CallBack)dic[eventTypee] + callBack;
}
/// <summary>
/// 移除监听事件
/// </summary>
/// <param name="eventTypee"></param>
/// <param name="callBack"></param>
public static void RemoveListener(EventTypee eventTypee,CallBack callBack)
{
//异常抛出
if (dic.ContainsKey(eventTypee))
{
Delegate m = dic[eventTypee];
if(m == null)
{
throw new Exception(string.Format("错误;事件{0}没有添加", eventTypee));
}
else if (m.GetType()!= callBack.GetType())
{
throw new Exception(string.Format("移除错误,事件{0}于事件{1}为不同委托", m.GetType(), callBack.GetType()));
}
}
else
{
throw new Exception(string.Format("错误,没有事件{0}", eventTypee));
}
dic[eventTypee] = (CallBack)dic[eventTypee] - callBack;
if (dic[eventTypee] == null)
{
dic.Remove(eventTypee);
}
}
/// <summary>
/// 事件的广播
/// </summary>
/// <param name="eventTypee"></param>
public static void Broadcast(EventTypee eventTypee)
{
Delegate m;
if (dic.TryGetValue(eventTypee, out m))
{
CallBack callBack = m as CallBack;//强制转换失败时,会返回 null
if(callBack != null)
{
callBack();
}
else
{
throw new Exception(string.Format("错误,事件已存在", eventTypee));
}
}
}
}
进行使用:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
private void Awake()
{
EventCenter.AddListener(EventTypee.test, Show1);
}
private void Show1()
{
Debug.Log("广播成功");
}
private void OnDestroy()
{
EventCenter.RemoveListener(EventTypee.test, Show1);
}
public void OnShowBtnClick()
{
EventCenter.Broadcast(EventTypee.test);
}
}