观察者模式- 消息订阅分发机制的实际应用

在项目中,脚本相互引用会造成耦合性的增加,而使用消息订阅分发,可以解耦合。
using UnityEngine;
using System.Collections.Generic;
using System;

/// <summary>
/// 委托事件类型Typ
/// </summary>
public enum MessageMediatType
{
    GetDiamond,     // 获得钻石
    GetMoney,        // 获得钱币
    LevelUp,        // 升级
}

public class MessageMediator
{
    //泛型委托
    public delegate void Act();  
    public delegate void Act<T>(T t);
    public delegate void Act<T1, T2>(T1 t1, T2 t2);
    public delegate void Act<T1, T2, T3>(T1 t1, T2 t2, T3 t3);
    public delegate void Act<T1, T2, T3, T4>(T1 t1, T2 t2, T3 t3, T4 t4);
    //public delegate void Act<T1, T2, T3, T4, T5>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5);

    /// <summary>
    /// 存取订阅事件字典 K为类型 value为相对应委托
    /// </summary>
    static Dictionary<MessageMediatType, Delegate> messageTable = new Dictionary<MessageMediatType, Delegate>();

    #region 注册监听

    /// <summary>
    /// 注册监听事件
    /// </summary>
    /// <param name="type">事件类型</param>
    /// <param name="act">事件处理方法</param>
    public static void AddListener(MessageMediatType type, Act act)
    {
        if (!messageTable.ContainsKey(type))  //如果要增加监听事件的类型不存在 就把新的类型和委托方法加载到管理订阅事件字典中
        {
            messageTable.Add(type, null);
        }

        Delegate d = messageTable[type];
        if (d != null && d.GetType() != act.GetType())  //如果在要加载监听事件已存在此类型 判断这个类型的处理方法是否为空 是否和自己要加载的处理方法类型相同 
        {
            Debug.LogError(string.Format("尝试为事件类型 {0} 添加不一致的签名的侦听器. 当前的监听器有type  {1}  而监听器被添加了type {2}", type, d.GetType().Name, act.GetType().Name));
            //Debug.LogError(string.Format("Attempting to add listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being added has type {2}", type, d.GetType().Name, act.GetType().Name));
        }
        else
        {
            messageTable[type] = (Act)messageTable[type] + act;
        }
    }

    /// <summary>
    /// 泛型委托注册监听
    /// </summary>
    /// <typeparam name="T">委托类型</typeparam>
    /// <param name="type"></param>
    /// <param name="act"></param>
    public static void AddListener<T>(MessageMediatType type, Act<T> act)
    {
        if (!messageTable.ContainsKey(type))
        {
            messageTable.Add(type, null);
        }

        Delegate d = messageTable[type];
        if (d != null && d.GetType() != act.GetType())
        {
            Debug.LogError(string.Format("尝试为事件类型 {0} 添加不一致的签名的侦听器. 当前的监听器有type  {1}  而监听器被添加了type {2}", type, d.GetType().Name, act.GetType().Name));
            // Debug.LogError(string.Format("Attempting to add listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being added has type {2}", type, d.GetType().Name, act.GetType().Name));
        }
        else
        {
            messageTable[type] = (Act<T>)messageTable[type] + act;
        }
    }
    public static void AddListener<T1, T2>(MessageMediatType type, Act<T1, T2> act)
    {
        if (!messageTable.ContainsKey(type))
        {
            messageTable.Add(type, null);
        }

        Delegate d = messageTable[type];
        if (d != null && d.GetType() != act.GetType())
        {
            Debug.LogError(string.Format("尝试为事件类型 {0} 添加不一致的签名的侦听器. 当前的监听器有type  {1}  而监听器被添加了type {2}", type, d.GetType().Name, act.GetType().Name));
            //Debug.LogError(string.Format("Attempting to add listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being added has type {2}", type, d.GetType().Name, act.GetType().Name));
        }
        else
        {
            messageTable[type] = (Act<T1, T2>)messageTable[type] + act;
        }
    }
    public static void AddListener<T1, T2, T3>(MessageMediatType type, Act<T1, T2, T3> act)
    {
        if (!messageTable.ContainsKey(type))
        {
            messageTable.Add(type, null);
        }

        Delegate d = messageTable[type];
        if (d != null && d.GetType() != act.GetType())
        {
            Debug.LogError(string.Format("尝试为事件类型 {0} 添加不一致的签名的侦听器. 当前的监听器有type  {1}  而监听器被添加了type {2}", type, d.GetType().Name, act.GetType().Name));
            //Debug.LogError(string.Format("Attempting to add listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being added has type {2}", type, d.GetType().Name, act.GetType().Name));
        }
        else
        {
            messageTable[type] = (Act<T1, T2, T3>)messageTable[type] + act;
        }
    }
    public static void AddListener<T1, T2, T3, T4>(MessageMediatType type, Act<T1, T2, T3, T4> act)
    {
        if (!messageTable.ContainsKey(type))
        {
            messageTable.Add(type, null);
        }

        Delegate d = messageTable[type];
        if (d != null && d.GetType() != act.GetType())
        {
            Debug.LogError(string.Format("尝试为事件类型 {0} 添加不一致的签名的侦听器. 当前的监听器有type  {1}  而监听器被添加了type {2}", type, d.GetType().Name, act.GetType().Name));
            //Debug.LogError(string.Format("Attempting to add listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being added has type {2}", type, d.GetType().Name, act.GetType().Name));
        }
        else
        {
            messageTable[type] = (Act<T1, T2, T3, T4>)messageTable[type] + act;
        }
    }
    #endregion

    #region 移除监听

    /// <summary>
    /// 移除监听委托事件
    /// </summary>
    /// <param name="type">委托事件类型</param>
    /// <param name="listenerBeingRemoved">委托事件处理方法</param>
    public static void RemoveListener(MessageMediatType type, Act listenerBeingRemoved)
    {
        if (messageTable.ContainsKey(type))   //查询储存委托事件的字典中是否存在相对应的类型 如果存在
        {
            Delegate d = messageTable[type]; 

            if (d == null)          //判断此类型的委托事件处理方法是否为空
            {
                Debug.LogError(string.Format("试图删除事件类型为\"{0}\" 的监听器,但是当前监听器是null.", type));
                //Debug.LogError(string.Format("Attempting to remove listener with for event type \"{0}\" but current listener is null.", type));
            }
            else if (d.GetType() != listenerBeingRemoved.GetType())  //如果此类型只的委托方法 和自己要移除的方法类型不同
            {
                Debug.LogError(string.Format("尝试用不一致的签名来删除事件类型 {0} 的监听器. 当前的监听器有类型 {1} 监听器被删除的类型为 {2}", type, d.GetType().Name, listenerBeingRemoved.GetType().Name));
                //Debug.LogError(string.Format("Attempting to remove listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being removed has type {2}", type, d.GetType().Name, listenerBeingRemoved.GetType().Name));
            }
            else
            {
                messageTable[type] = (Act)messageTable[type] - listenerBeingRemoved;   //吧此类型的委托处理发放从委托只移除
                if (d == null)   //如果移除后委托事件处理方法为空 就把此类型从存取订阅事件字典移除
                {
                    messageTable.Remove(type);
                }
            }
        }
        else
        {
            Debug.LogError(string.Format("试图将侦听器删除为 \"{0}\" 但是Messenger并不知道这个事件类型.", type));
            //Debug.LogError(string.Format("Attempting to remove listener for type \"{0}\" but Messenger doesn't know about this event type.", type));
        }
    }
    public static void RemoveListener<T>(MessageMediatType type, Act<T> listenerBeingRemoved)
    {
        if (messageTable.ContainsKey(type))
        {
            Delegate d = messageTable[type];

            if (d == null)
            {
                Debug.LogError(string.Format("试图删除事件类型为\"{0}\" 的监听器,但是当前监听器是null.", type));
                // Debug.LogError(string.Format("Attempting to remove listener with for event type \"{0}\" but current listener is null.", type));
            }
            else if (d.GetType() != listenerBeingRemoved.GetType())
            {
                Debug.LogError(string.Format("尝试用不一致的签名来删除事件类型 {0} 的监听器. 当前的监听器有类型 {1} 监听器被删除的类型为 {2}", type, d.GetType().Name, listenerBeingRemoved.GetType().Name));
                //Debug.LogError(string.Format("Attempting to remove listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being removed has type {2}", type, d.GetType().Name, listenerBeingRemoved.GetType().Name));
            }
            else
            {
                messageTable[type] = (Act<T>)messageTable[type] - listenerBeingRemoved;
                if (d == null)
                {
                    messageTable.Remove(type);
                }
            }
        }
        else
        {
            Debug.LogError(string.Format("Attempting to remove listener for type \"{0}\" but Messenger doesn't know about this event type.", type));
        }
    }
    public static void RemoveListener<T1, T2>(MessageMediatType type, Act<T1, T2> listenerBeingRemoved)
    {
        if (messageTable.ContainsKey(type))
        {
            Delegate d = messageTable[type];

            if (d == null)
            {
                Debug.LogError(string.Format("试图删除事件类型为\"{0}\" 的监听器,但是当前监听器是null.", type));
                //Debug.LogError(string.Format("Attempting to remove listener with for event type \"{0}\" but current listener is null.", type));
            }
            else if (d.GetType() != listenerBeingRemoved.GetType())
            {
                Debug.LogError(string.Format("尝试用不一致的签名来删除事件类型 {0} 的监听器. 当前的监听器有类型 {1} 监听器被删除的类型为 {2}", type, d.GetType().Name, listenerBeingRemoved.GetType().Name));
                //Debug.LogError(string.Format("Attempting to remove listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being removed has type {2}", type, d.GetType().Name, listenerBeingRemoved.GetType().Name));
            }
            else
            {
                messageTable[type] = (Act<T1, T2>)messageTable[type] - listenerBeingRemoved;
                if (d == null)
                {
                    messageTable.Remove(type);
                }
            }
        }
        else
        {
            Debug.LogError(string.Format("试图将侦听器删除为 \"{0}\" 但是Messenger并不知道这个事件类型.", type));
            //Debug.LogError(string.Format("Attempting to remove listener for type \"{0}\" but Messenger doesn't know about this event type.", type));
        }
    }
    public static void RemoveListener<T1, T2, T3>(MessageMediatType type, Act<T1, T2, T3> listenerBeingRemoved)
    {
        if (messageTable.ContainsKey(type))
        {
            Delegate d = messageTable[type];

            if (d == null)
            {
                Debug.LogError(string.Format("试图删除事件类型为\"{0}\" 的监听器,但是当前监听器是null.", type));
                //Debug.LogError(string.Format("Attempting to remove listener with for event type \"{0}\" but current listener is null.", type));
            }
            else if (d.GetType() != listenerBeingRemoved.GetType())
            {
                Debug.LogError(string.Format("尝试用不一致的签名来删除事件类型 {0} 的监听器. 当前的监听器有类型 {1} 监听器被删除的类型为 {2}", type, d.GetType().Name, listenerBeingRemoved.GetType().Name));
                //Debug.LogError(string.Format("Attempting to remove listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being removed has type {2}", type, d.GetType().Name, listenerBeingRemoved.GetType().Name));
            }
            else
            {
                messageTable[type] = (Act<T1, T2, T3>)messageTable[type] - listenerBeingRemoved;
                if (d == null)
                {
                    messageTable.Remove(type);
                }
            }
        }
        else
        {
            Debug.LogError(string.Format("试图将侦听器删除为 \"{0}\" 但是Messenger并不知道这个事件类型.", type));
            // Debug.LogError(string.Format("Attempting to remove listener for type \"{0}\" but Messenger doesn't know about this event type.", type));
        }
    }
    public static void RemoveListener<T1, T2, T3, T4>(MessageMediatType type, Act<T1, T2, T3, T4> listenerBeingRemoved)
    {
        if (messageTable.ContainsKey(type))
        {
            Delegate d = messageTable[type];

            if (d == null)
            {
                Debug.LogError(string.Format("试图删除事件类型为\"{0}\" 的监听器,但是当前监听器是null.", type));
                //Debug.LogError(string.Format("Attempting to remove listener with for event type \"{0}\" but current listener is null.", type));
            }
            else if (d.GetType() != listenerBeingRemoved.GetType())
            {
                Debug.LogError(string.Format("尝试用不一致的签名来删除事件类型 {0} 的监听器. 当前的监听器有类型 {1} 监听器被删除的类型为 {2}", type, d.GetType().Name, listenerBeingRemoved.GetType().Name));
                //Debug.LogError(string.Format("Attempting to remove listener with inconsistent signature for event type {0}. Current listeners have type {1} and listener being removed has type {2}", type, d.GetType().Name, listenerBeingRemoved.GetType().Name));
            }
            else
            {
                messageTable[type] = (Act<T1, T2, T3, T4>)messageTable[type] - listenerBeingRemoved;
                if (d == null)
                {
                    messageTable.Remove(type);
                }
            }
        }
        else
        {
            Debug.LogError(string.Format("试图将侦听器删除为 \"{0}\" 但是Messenger并不知道这个事件类型.", type));
            //Debug.LogError(string.Format("Attempting to remove listener for type \"{0}\" but Messenger doesn't know about this event type.", type));
        }
    }

    /// <summary>
    /// 清空指定类型的委托事件处理方法
    /// </summary>
    /// <param name="type">要删除的类型</param>
    public static void RemoveAllListener(MessageMediatType type)
    {
        if (messageTable.ContainsKey(type))
        {
            messageTable[type] = null;
            messageTable.Remove(type);
        }
        else
        {

            Debug.LogError(string.Format("试图将侦听器删除为 \"{0}\" 但是Messenger并不知道这个事件类型.", type));
            // Debug.LogError(string.Format("Attempting to remove listener for type \"{0}\" but Messenger doesn't know about this event type.", type));
        }
    }

    #endregion

    #region 分配消息

    /// <summary>
    /// 当收到消息后分配消息
    /// </summary>
    /// <param name="type">消息的类型</param>
    public static void Dispatch(MessageMediatType type)
    {
        Delegate d;  //声明一个用来储存 处理此类型委托
        if (messageTable.TryGetValue(type, out d))
        {
            Act callback = d as Act;

            if (callback != null)
            {
                callback();  //如果此类型的消息处理事件方法不为空执行方法
            }
            else
            {
                Debug.LogError(string.Format("没有这样的事件类型为 {0}", type));
                //Debug.LogError(string.Format("no such event type {0}", type));
            }
        }
    }
    public static void Dispatch<T>(MessageMediatType type, T param1)
    {
        Delegate d;
        if (messageTable.TryGetValue(type, out d))
        {
            Act<T> callback = d as Act<T>;

            if (callback != null)
            {
                callback(param1);
            }
            else
            {
                Debug.LogError(string.Format("没有这样的事件类型为 {0}", type));
                //Debug.LogError(string.Format("no such event type {0}", type));
            }
        }
    }
    public static void Dispatch<T1, T2>(MessageMediatType type, T1 param1, T2 param2)
    {
        Delegate d;
        if (messageTable.TryGetValue(type, out d))
        {
            Act<T1, T2> callback = d as Act<T1, T2>;

            if (callback != null)
            {
                callback(param1, param2);
            }
            else
            {
                Debug.LogError(string.Format("没有这样的事件类型为 {0}", type));
               // Debug.LogError(string.Format("no such event type {0}", type));
            }
        }
    }
    public static void Dispatch<T1, T2, T3>(MessageMediatType type, T1 param1, T2 param2, T3 param3)
    {
        Delegate d;
        if (messageTable.TryGetValue(type, out d))
        {
            Act<T1, T2, T3> callback = d as Act<T1, T2, T3>;

            if (callback != null)
            {
                callback(param1, param2, param3);
            }
            else
            {
                Debug.LogError(string.Format("没有这样的事件类型为 {0}", type));
                //Debug.LogError(string.Format("no such event type {0}", type));
            }
        }
    }
    public static void Dispatch<T1, T2, T3, T4>(MessageMediatType type, T1 param1, T2 param2, T3 param3, T4 param4)
    {
        Delegate d;
        if (messageTable.TryGetValue(type, out d))
        {
            Act<T1, T2, T3, T4> callback = d as Act<T1, T2, T3, T4>;

            if (callback != null)
            {
                callback(param1, param2, param3, param4);
            }
            else
            {
                Debug.LogError(string.Format("没有这样的事件类型为 {0}", type));
                //Debug.LogError(string.Format("no such event type {0}", type));
            }
        }
    }
    #endregion
}
测试代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Tset : MonoBehaviour {
    void Start()
    {
        //注册监听获得金币事件  参数一为事件类型 参数二为事件回调函数
        MessageMediator.AddListener<int>(MessageMediatType.GetMoney, MoneyCallBack);  
        //事件触发    执行回调函数
        MessageMediator.Dispatch(MessageMediatType.GetMoney, 100);
        //移除所有监听法法
        MessageMediator.RemoveListener<int>(MessageMediatType.GetMoney, MoneyCallBack);


        MessageMediator.AddListener<int, float>(MessageMediatType.LevelUp, LevelUpCallBack1);
        MessageMediator.AddListener<int, float>(MessageMediatType.LevelUp, LevelUpCallBack2);
        MessageMediator.Dispatch(MessageMediatType.LevelUp, 2, 392f);

        MessageMediator.RemoveListener<int, float>(MessageMediatType.LevelUp, LevelUpCallBack1);
        MessageMediator.Dispatch<int, float>(MessageMediatType.LevelUp, 3, 256f);

    }

    /// <summary>
    /// 获得金币的方法
    /// </summary>
    /// <param name="coin"></param>
    private void MoneyCallBack(int coin)
    {
        Debug.Log("获得金币回调函数  " + coin);
    }

    /// <summary>
    /// 增加等级增加经验的方法1
    /// </summary>
    /// <param name="level"></param>
    /// <param name="exp"></param>
    private void LevelUpCallBack1(int level, float exp)
    {
        Debug.Log("增加等级,增加经验,回调函数 1 。" + level + " " + exp);
    }

    /// <summary>
    ///  增加等级增加经验的方法2
    /// </summary>
    /// <param name="level"></param>
    /// <param name="exp"></param>
    private void LevelUpCallBack2(int level, float exp)
    {
        Debug.Log("增加等级,增加经验,回调函数 2 " + level + " " + exp);
    }
}


猜你喜欢

转载自blog.csdn.net/qq_39741605/article/details/80677878