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

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. git命令详解( 四 )

    此篇为git命令详解的第四篇,话不多说,我们直接上知识点好吧 git Push 偏离的工作 gitPush: 此命令负责将你的变更上传到指定的远程仓库,并在远程仓库上合并你的新提交记录.一旦 git ...

  2. Android之移动热修复

    阿里云推出了移动热修复服务,听说这个服务傻瓜式接入,性能相对较好,对新技术比较好奇的我决定尝试一下. 1.首先,需要开通这个服务,创建应用 2.然后,在项目中接入服务.按照文档所述 第一步:gradl ...

  3. node中__dirname、__filename、process.cwd()、process.chdir()表示的路径

    直接上结论:__dirname 表示当前文件所在的目录的绝对路径__filename 表示当前文件的绝对路径module.filename ==== __filename 等价process.cwd( ...

  4. 纯CSS选项卡

    html: <!doctype html> <html> <head> <meta charset="utf-8"> <tit ...

  5. 分布式文件系统(HDFS)与 linux系统文件系统 对比

    初次接触分布式文件系统,有很多迷惑.通过参考网络文章,这里进行对比一下Hadoop 分布式文件系统(HDFS)与 传统文件系统之间的关系:   Linux 文件系统 分布式文件系统 块 块对应物理磁盘 ...

  6. SQL mysql优化

    慢查询 如何通过慢查日志发现有问题的SQL? 查询次数多且每次查询占用时间长的SQL pt-query-digest分析前几个查询 IO大的SQL pt-query-diges分析中的Rows exa ...

  7. January 20th, 2018 Week 3rd Saturday

    We may encounter many defeats but we must not be defeated. 我们可能会失败很多次,但决不能被打败. As long as we are con ...

  8. Alpha冲刺! Day8 - 砍柴

    Alpha冲刺! Day8 - 砍柴 今日已完成 晨瑶:写了部分gitkraken团队协作教程:讨论关于继承baseActivity因为需要参数无法通过override去实现函数,并且initData ...

  9. centos7下安装docker(3.1创建镜像commit)

    docker commit创建镜像 步骤:1.运行容器 2.修改容器 3.将容器保存为镜像 1. 注:-it是以交互模式进入容器,并打开终端 2.安装一个vim进行修改镜像 yum install - ...

  10. Elasticsearch 数据搜索篇·【入门级干货】===转

    ES即简单又复杂,你可以快速的实现全文检索,又需要了解复杂的REST API.本篇就通过一些简单的搜索命令,帮助你理解ES的相关应用.虽然不能让你理解ES的原理设计,但是可以帮助你理解ES,探寻更多的 ...