【Unity】事件的监听与广播,高度解耦合

事件的监听与广播,高度解耦合。

一些我自己的理解
  • delegate可存储函数指针;

  • 它的一些特性像是类——例如需要实例化(使用new关键字),可以使用+=符号直接添加函数委托;

  • 需要事先定义一个委托模板(限定传入参数,和返回参数类型)。

顺带一提,eventdelegate用起来是一样的。都可以用像是+=的符号添加委托,都像是函数一样被调用就会调用所有注册的委托。但有一个明显的使用区别: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);
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容