一、首先定义一份消息号(消息号用来标记发出的每一条消息,接收者通过注册要监听的消息号来监听相应的消息)

public enum MSG_IDS
{
NONE = -,
MSG_TEST01 = ,
MSG_TEST02 = ,
}

二、然后定义一个消息类,作为消息的载体

public class Notification {
    MSG_IDS id = MSG_IDS.NONE; //消息号
    public MSG_IDS Id{get { return id; }}
    Dictionary<string, object> infos;// 消息内容,消息要传递的具体信息     public Notification(MSG_IDS id)
    {
        this.id = id;
        infos = new Dictionary<string, object>();
    }
   //消息索引器,用字符串做key(注意key不能重复)
    public object this[string id]
    {
        get {
            if(infos.ContainsKey(id))
            {
                return infos[id];
            }else
            {
                Debug.LogError("不存在参数:" + id);
                return null;
            }
        }
        set {
            if(infos.ContainsKey(id))
            {
                infos[id] = value;
            }else
            {
                infos.Add(id, value);
            }
        }
    }
}

三、组件ID生成器,这个主要用于标记组件内的事件,以便移除

public class IDCreator{
uint curMaxId = ;
List<uint> recycleIndex = new List<uint>();
public uint GetNewID()
{
if (recycleIndex.Count > )
{
uint id = recycleIndex[recycleIndex.Count - ];
recycleIndex.RemoveAt(recycleIndex.Count - );
return id;
}
if (curMaxId == UInt32.MaxValue)
{
Debug.LogError("ID 溢出");
return curMaxId;
}
return curMaxId++;
}
public void Recycle(uint id)
{
recycleIndex.Add(id);
}
}

四、消息管理器

public class MsgController{
    public delegate void MsgDel(Notification notify);
    private Dictionary<MSG_IDS, List<MsgDel>> MsgDic;
    private Dictionary<uint, Dictionary<MSG_IDS, MsgDel>> MsgDicMap;
    private static MsgController _instance = null;
    
    public static MsgController Instance
    {
        get
        {
            if(_instance == null)_instance = new MsgController();
            return _instance;
        }
    }     private static IDCreator _componentID = null;
    /// <summary>
    /// 组件唯一id生成器
    /// </summary>
    public static IDCreator ComponentID
    {
        get
        {
            if (_componentID == null) _componentID = new IDCreator();
            return _componentID;
        }
    }     /// <summary>
    /// 添加监听
    /// </summary>
    /// <param name="msgId"></param>
    /// <param name="msg"></param>
    public void AddNotification(uint index, MSG_IDS msgId, MsgDel msg)
    {
        try
        {
            if (MsgDic == null)
            {
                MsgDic = new Dictionary<MSG_IDS, List<MsgDel>>();
            }
            if (MsgDicMap == null)
            {
                MsgDicMap = new Dictionary<uint, Dictionary<MSG_IDS, MsgDel>>();
            }             //按消息号保存消息列表
            if (!MsgDic.ContainsKey(msgId))
            {
                List<MsgDel> list = new List<MsgDel>();
                MsgDic.Add(msgId, list);
            }
            MsgDic[msgId].Add(msg);
            //按id索引保存消息列表
            if (!MsgDicMap.ContainsKey(index))
            {
                Dictionary<MSG_IDS, MsgDel> map = new Dictionary<MSG_IDS, MsgDel>();
                MsgDicMap.Add(index, map);
            }
            MsgDicMap[index].Add(msgId, msg);
        }catch(Exception e)
        { throw (e); }
    }     /// <summary>
    /// 移除一个组件上的所有事件
    /// </summary>
    /// <param name="index"></param>
    public void RemoveAllNotification(uint index)
    {
        if(MsgDicMap.ContainsKey(index))
        {
            foreach (var map in MsgDicMap[index])
            {
                RemoveNotification(map.Key, map.Value);
            }
        MsgDicMap.Remove(index);
            _componentID.Recycle(index);//回收id以便重复利用
        }
    }     /// <summary>
    /// 移除某个id对应的监听事件
    /// </summary>
    /// <param name="msgId"></param>
    /// <param name="msg"></param>
    public void RemoveNotification(MSG_IDS msgId, MsgDel msg)
    {
        try
        {
            MsgDic[msgId].Remove(msg);
        }catch(Exception e)
        {
            Debug.LogError("找不到消息:" + msgId);
            throw(e);
        }
    }     /// <summary>
    /// 发送通知
    /// </summary>
    /// <param name="notify"></param>
    public void SendMsg(Notification notify)
    {
        try
        {
            if (MsgDic.ContainsKey(notify.Id))
            {
                List<MsgDel> msgs = MsgDic[notify.Id];
                for (int i = 0; i < msgs.Count; i++)
                {
                    msgs[i](notify);
                }
            }
        }catch(Exception e)
        { throw (e); }
    }

四、发送、接收消息实例

public class Sender : MonoBehaviour {
   int n = 0;public void Btn1()
{
Notification notify = new Notification(MSG_IDS.MSG_TEST01);
        notify["text"] = "第" + (++n) + "次 string ";
        MsgController.Instance.SendMsg(notify);
}
  int m = 0;public void Btn2()
{
Notification notify = new Notification(MSG_IDS.MSG_TEST02);
        notify["value"] = ++m;
        MsgController.Instance.SendMsg(notify);
}
}
public class Listener01 : MonoBehaviour
{
    uint eventIndex = 0;
    void OnEnable()
    {
        eventIndex = MsgController.ComponentID.GetNewID();//获取一个组件id,这个id的意义在于,当一个组件上加了很多监听时,不需要一个个移除。一个个移除很麻烦,也很容易出错
        MsgController.Instance.AddNotification(eventIndex, MSG_IDS.MSG_TEST01, MsgListener01);
        MsgController.Instance.AddNotification(eventIndex, MSG_IDS.MSG_TEST02, MsgListener02);
    }     void OnDisable()
    {
        MsgController.Instance.RemoveAllNotification(eventIndex);//移除所有组件id为eventIndex的监听(并不关心eventIndex的值是多少)
    }     public void MsgListener01(Notification notify)
    {
        string text = (string)notify["text"];
        Debug.LogError(transform.name + " " + text);
    }     public void MsgListener02(Notification notify)
    {
        int v = (int)notify["value"];
        Debug.LogError(transform.name + " " + v.ToString());
    }
}

Unity 消息管理(观察煮模式)的更多相关文章

  1. 4.Node.js 微信消息管理

    一.写在前面的话   当用户发送消息给公众号时(或某些特定的用户操作引发的事件推送时),会产生一个POST请求,开发者可以在响应包(Get)中返回特定XML结构,来对该消息进行响应.   消息推送也是 ...

  2. ActiveMQ基本详解与总结& 消息队列-推/拉模式学习 & ActiveMQ及JMS学习

    转自:https://www.cnblogs.com/Survivalist/p/8094069.html ActiveMQ基本详解与总结 基本使用可以参考https://www.cnblogs.co ...

  3. 九、EnterpriseFrameWork框架基础功能之消息管理

    记得阿朱在<走出软件作坊>一书中有一章讲客户提的需求太邪门了,鼠标键盘不太会用要程序员开发一个语音输入功能,还要系统中带类似QQ的功能:确实刚开始的客户的想法有点天真,但是随着信息化的越来 ...

  4. RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.0 版新增消息管理

    在V3.0版本的Web(Mvc.WebForm)与WinForm中我们新增了“消息管理”模块.“消息管理”模块是对框架的所有消息进行管理.通过左侧的消息分类可以查看所选分类的所有消息列表.在主界面上我 ...

  5. 微信公众号开发C#系列-7、消息管理-接收事件推送

    1.概述 在微信用户和公众号产生交互的过程中,用户的某些操作会使得微信服务器通过事件推送的形式通知到开发者在开发者中心处设置的服务器地址,从而开发者可以获取到该信息.其中,某些事件推送在发生后,是允许 ...

  6. 微信公众号开发C#系列-6、消息管理-普通消息接受处理

    1.概述 通过前面章节的学习,我们已经对微信的开发有了基本的掌握与熟悉,基本可以上手做复杂的应用了.本篇我们将详细讲解微信消息管理中普通消息的接收与处理.当普通微信用户向公众账号发消息时,微信服务器将 ...

  7. 使用Ajax轮询模拟简单的站内信箱(消息管理)功能

    前一段时间项目需要写一个类似于站内信箱的消息管理的功能,由于对前端不是很熟悉,刚开始不知道怎么做,后来看了网上的方案,现模拟一个非常简单的消息管理. 我们首先看一下最终效果的样式,就是非常简单的一个样 ...

  8. 17.0-uC/OS-III消息管理

    消息传递 有些情况下任务或ISR与另一个任务间进行通信,这种信息交换叫做作业间的通信. 可以有两种方法实现这种通信: 全局变量. 发送消息. 1.果使用全局变量,任务或ISR就须确保它独占该变量.如果 ...

  9. Unity消息简易框架 Advanced C# messenger

    Unity消息简易框架 Advanced C# messenger Unity C# 消息机制  [转载 雨凇MOMO博客] https://www.xuanyusong.com/archives/2 ...

随机推荐

  1. Salesforce Live Agent 简介

    Live Agent Salesforce 内置了即时聊天功能--Live Agent,可以用来作为客服工具. 本文简单介绍了使用 Live Agent 的步骤,主要包含: 启用 Live Agent ...

  2. 配置文件读取工具类--PropertiesUtil

    /** * 属性工具类 * @author admin * 参考:https://www.cnblogs.com/doudouxiaoye/p/5693454.html */ public class ...

  3. DB2表被锁,如何解锁

    原因与解决方案 1.原因:修改表结构表结构发生变化后再对表进行任何操作都不被允许,SQLState为57016(因为表不活动,所以不能对其进行访问),由于修改了表字段权限,导致表处于不可用状态 2.解 ...

  4. bootstrap-select插件 多选框

    HeBeiTianQi.jsp页面 1 <!--bootstrap-select .css引用--> 2 <link rel="stylesheet" href= ...

  5. dumpe2fs 命令的使用,转储 ext2/ext3/ext4 文件系统信息

    使用man 命令可以查看 dumpe2fs 命令具体的使用的方法: NAME dumpe2fs - dump ext2/ext3/ext4 filesystem information SYNOPSI ...

  6. 利用PCA进行故障监测

    利用PCA进行故障监测,传统的统计指标有两种:Hotelling-T2和平方预测误差(Squared prediction error, SPE).T2统计量反映了每个主成分在变化趋势和幅值上偏离模型 ...

  7. Mac命令行使用tree查看目录结构

    默认tree命令是无法使用的,可以使用homebrew install tree安装. 如果直接使用tree,查看的目录里面含有中文字符的目录或文件时会出现汉字不能显示的问题,可以使用tree -N查 ...

  8. tkinter学习系列之(八) Canvas控件

    目录 目录 前言 (一)carves创建方法 (二)carves的画图方法 目录 前言 由于最近想在tkinter里内嵌matplotlib,由于用到tkinter里的carves控件,先学习一下. ...

  9. [java大数据面试] 2018年4月百度面试经过+三面算法题:给定一个数组,求和为定值的所有组合.

    给定一个数组,求和为定值的所有组合, 这道算法题在leetcode应该算是中等偏下难度, 对三到五年工作经验主要做业务开发的同学来说, 一般较难的也就是这种程度了. 简述经过: 不算hr面,总计四面, ...

  10. win10下SVN图标不显示

    win10系统的SVN图标不现实了.正常情况下,会在文件夹上有一个对勾 但是对勾以及所有的SVN图标都突然消失了,都不知道文件什么状态了. 经过一通搜索,发现问题所在(都指向注册表图标被占用).原因就 ...