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

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. JS之this应用详解

    目录 1. this作为全局变量2. 作为对象方法的调用3. 作为构造函数调用4. apply调用 this是Javascript语言的一个关键字.它代表函数运行时,自动生成的一个内部对象,只能在函数 ...

  2. Salesforce小知识:在简档中设置Visualforce页面的权限

    简档(Profile)中的 Visualforce 页面访问权限 在Salesforce中,对于自定义的简档,可以设置"Visualforce 页面访问"的权限. Visualfo ...

  3. Linux高可靠技术

    1.进程挂死时,有后台监控程序检测重新拉起. 2.进程占用系统资源超过ulimit限定的资源时,会被ulimit杀死,同时配合后台监控程序,重新拉起进程,实现进程可靠性. 3.Linux系统的高可靠性 ...

  4. LeetCode题解之Binary Tree Pruning

    1.题目描述 2.问题分析 使用递归 3.代码 TreeNode* pruneTree(TreeNode* root) { if (root == NULL) return NULL; prun(ro ...

  5. MongoDB的安装与python操作MongoDB

    一.安装MongoDB 因为我个人使用的是windows,就只记录下windows下的安装 1.下载安装 就是官网,下载msi,选个路径安装 2.配置 看见别的地方说需要手动在bin同级目录创建dat ...

  6. apache配置CA证书通过https通信

    Apache Httpd 2.2 实现https加密通讯 实际生产中CA证书一般是向一些专业认证的国际机构来进行申请的.我们会模拟使用OpenSSL生成的证书,来实现Apache的安全加密通讯,这与实 ...

  7. npm包开发(whale-makelink)

    whale-makelink是一个npm工具,是强业务的工具,可以将当前工程目录下的项目文件夹,在README中生成项目的链接地址.Demo. 一.npm init 使用npm init生成packa ...

  8. 通过SQL直接插入、修改ArcGIS SDE空间表中的数据

    基于Arcgis Server 10.1 +Oracle 11g环境测试 ArcGIS SDE ? 1 2 INSERT INTO CAMERA_INFO(OBJECTID,ID,SHAPE)     ...

  9. 马哥Python视频

    链接:https://pan.baidu.com/s/1KMXqdXlaIjZ3OaZ-PUwE9A 密码私聊我

  10. mysql explain(转)

    explain显示了mysql如何使用索引来处理select和表连接 转自http://blog.csdn.net/zhuxineli/article/details/14455029 explain ...