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

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校验身份证号的合法性

    前端表单中有身份证号的校验,下边是用JS来校验身份证号的合法性. 中国居民身份证号码编码规则 第一.二位表示省(自治区.直辖市.特别行政区). 第三.四位表示市(地级市.自治州.盟及国家直辖市所属市辖 ...

  2. python之socketserver ftp功能简单讲解

    TCP协议中的socket一次只能和一个客户端通信,然而socketserver可以实现和多个客户端通信. 它是在socket的基础上进行了一层封装,底层还是调用的socket # 服务端 impor ...

  3. SQLite 知识摘要 --- 事务

    在许多时候,我们在使用大数据的时候会发现,尽管sqlite数据库的执行效率已经很快了,但是还是满足不了我们的需求,这时候我们会很容易考虑到使用并发的方式去访问sqlite数据库,但是sqlite数据独 ...

  4. Twitter基于R语言的时序数据突变检测(BreakoutDetection)

    Twitter开源的时序数据突变检测(BreakoutDetection),基于无参的E-Divisive with Medians (EDM)算法,比传统的E-Divisive算法快3.5倍以上,并 ...

  5. recovery 升级过程执行自定义shell命令

    有时候我们需要,在升级的过程中,执行一些shell命令,来完成我们的一些需求,利用升级过程,进行一些特殊化的操作,思路如下: 第一: 把我们需要执行的命令,写成一个test.sh脚本,然后在recov ...

  6. WebSocket实现简单的在线聊天

    SuperWebSocket在WebService中的应用 最开始使用是寄托在IIS中,发布之后测试时半个小时就会断开,所以改为WindowsService 1. 新建Windows服务项目[Test ...

  7. vuejs组件库pk介绍

    vuejs可以说是近2年多以来最火的前端框架,随之而来就产生了非常多的组件库,我们来看看其中比较著名和人气旺盛的几个 1. Vuetify-符合material design设计理念, star数量7 ...

  8. Python和Lua的默认作用域以及闭包

    默认作用域 前段时间学了下Lua,发现Lua的默认作用域和Python是相反的.Lua定义变量时默认变量的作用域是全局(global,这样说不是很准确,Lua在执行x = 1这样的语句时会从当前环境开 ...

  9. 【ReactNative】Mac下分分钟打包 Android apk

    时间:2016-11-20 09:17:07 地址:https://github.com/zhongxia245/blog/issues/52 Mac 下 ReactNative如何打包构建Andro ...

  10. 用智能TFT液晶模块这种串口屏做产品界面设计太简单了,大大的节省了开发时间

    随着科技的发展,TFT液晶显示屏在我们日常中可以随处可见. 工业设备上的显示也逐渐由段式显示.黑白显示转向彩色的TFT液晶显示屏. 普通的TFT液晶显示屏由于开发起来比较麻烦, 需要嵌入式工程时写程序 ...