又到了周末时间,今天没有去公司赚加班费,在家里好好休息一下?不存在的,这辈子不写代码是不存在的!

今天我们来讲讲消息系统。

很多刚入行的小白同学在处理类与类之间的关系时,总是比较简单除暴的处理,直接把那个类引用到这个类,把这个类引用到那个类,最后造成很多类相互引用,形成一个复杂的蜘蛛网式的引用关系,这就是代码的耦合。那这个又有什么关系呢?那么我们就通俗的讲一下这个问题。

打个比方,同学们的期末成绩出来了,然后学校派一个人到全校的学生家里一个个通知成绩,第二天这个人辞职了哈哈!那么学校会怎么做呢?在远古时代,学校一般都是会在学校的公示栏上公布所有学生的期末成绩,而在如今的互联网时代,学校一般都是把所有学生的期末成绩发布到自己系统内,想要知道成绩的同学自己去查看,这样就不会有人辞职了哈哈。学校的系统不认识是哪个学生,也不关心哪个学生要不要看自己的成绩,反正我发布出去了,有兴趣要看的同学可以自己去查看,我们之间没有任何的绯闻,你成绩好不好和我没关系。

这个过程就叫解耦,类与类之间不再有耦合关系,没有小三,也没有小四,家和万事兴。

所以我们引入了事件机制,事件机制其实是一种叫做观察者模式的设计模式,事件的本质是一种方法的委托(Delegate),把回调方法委托到事件管理器,当条件达到时,通过事件key来告诉事件管理器可以执行那些委托的方法。

好了,接下来XM就为大家讲解一套完整的消息系统。

1.首先我们先来定义一下消息结构的接口IMessage。

// **********************************************************************
// Copyright (C) XM
// Author: 吴肖牧
// Date: 2018-04-13
// Desc:
// **********************************************************************using System.Collections;
using System.Collections.Generic;
using UnityEngine;public interface IMessage
{/// <summary>/// 事件类型,Key/// </summary>int Type { get; set; }/// <summary>/// 发送者/// </summary>System.Object Sender { get; set; }/// <summary>/// 参数/// </summary>System.Object[] Params { get; set; }/// <summary>/// 转字符串/// </summary>/// <returns></returns>string ToString();
}

为什么我会用int类型而不是用string类型作为消息的key呢?大家可以自己思考一下。

2.接口IMessage的实现Message。

// **********************************************************************
// Copyright (C) XM
// Author: 吴肖牧
// Date: 2018-04-13
// Desc:
// **********************************************************************using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Message : IMessage {public int Type { get; set; }public System.Object[] Params { get; set; }public System.Object Sender { get; set; }public override string ToString(){string arg = null;if (Params != null){for (int i = 0; i < Params.Length; i++){if ((Params.Length > 1 && Params.Length - 1 == i) || Params.Length == 1){arg += Params[i];}else{arg += Params[i] + " , ";}}}return Type + " [ " + ((Sender == null) ? "null" : Sender.ToString()) + " ] " + " [ " + ((arg == null) ? "null" : arg.ToString()) + " ] ";}public Message Clone(){return new Message(Type, Params, Sender);}public Message(int type){Type = type;}public Message(int type, params System.Object[] param){Type = type;Params = param;}public Message(int type, System.Object sender, params System.Object[] param){Type = type;Params = param;Sender = sender;}
}

3.接下来我们定义一下消息的类型,这里我把消息类型分成了常用消息,战斗消息,协议消息3大类,而不是都写在一个类型里面,结构清晰明了。

// **********************************************************************
// Copyright (C) XM
// Author: 吴肖牧
// Date: 2018-04-13
// Desc: 消息的类型
// **********************************************************************/// <summary>
/// 消息的类型
/// </summary>
public enum MessageType
{/// <summary>/// 启动/// </summary>START_UP = 1000,/// <summary>/// 解压/// </summary>UNPACK,/// <summary>/// 更新/// </summary>UPDATE,/// <summary>/// 更新完成/// </summary>UPDATE_COMPLETE,
}/// <summary>
/// 战斗的类型
/// </summary>
public enum BattleEvent
{/// <summary>/// 攻击/// </summary>Attack = 10000,
}/// <summary>
/// 协议的类型
/// </summary>
public enum ProtocolEvent
{}

4.然后我们定义一下消息派发者的接口IDispatcher。

// **********************************************************************
// Copyright (C) XM
// Author: 吴肖牧
// Date: 2018-04-13
// Desc:
// **********************************************************************using System.Collections;
using System.Collections.Generic;
using UnityEngine;public interface IDispatcher
{void AddListener(int type, EventListenerDelegate listener);void RemoveListener(int type, EventListenerDelegate listener);void SendMessage(Message evt);void SendMessage(int type, params System.Object[] param);void Clear();
}

5.接口IDispatcher的实现Dispatcher。

// **********************************************************************
// Copyright (C) XM
// Author: 吴肖牧
// Date: 2018-04-13
// Desc:
// **********************************************************************using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public delegate void EventListenerDelegate(Message evt);public class Dispatcher : Singleton<Dispatcher>, IDispatcher
{private Dictionary<int, EventListenerDelegate> events = new Dictionary<int, EventListenerDelegate>();public void AddListener(int type, EventListenerDelegate listener){if (listener == null){XMDebug.LogError("AddListener: listener不能为空");return;}EventListenerDelegate myListener = null;events.TryGetValue(type, out myListener);events[type] = (EventListenerDelegate)Delegate.Combine(myListener, listener);}public void RemoveListener(int type, EventListenerDelegate listener){if (listener == null){XMDebug.LogError("RemoveListener: listener不能为空");return;}events[type] = (EventListenerDelegate)Delegate.Remove(events[type], listener);}public void Clear(){events.Clear();}public void SendMessage(Message evt){EventListenerDelegate listenerDelegate;if (events.TryGetValue(evt.Type, out listenerDelegate)){try{if (listenerDelegate != null){listenerDelegate(evt);}}catch (System.Exception e){XMDebug.LogError("SendMessage:", evt.Type.ToString(), e.Message, e.StackTrace, e);}}}public void SendMessage(int type, params System.Object[] param){EventListenerDelegate listenerDelegate;if (events.TryGetValue(type, out listenerDelegate)){Message evt = new Message(type, param);try{if (listenerDelegate != null){listenerDelegate(evt);}}catch (System.Exception e){XMDebug.LogError("SendMessage:", evt.Type.ToString(), e.Message, e.StackTrace, e);}}}public void AddListener(MessageType type, EventListenerDelegate listener){AddListener((int)type, listener);}public void AddListener(BattleEvent type, EventListenerDelegate listener){AddListener((int)type, listener);}public void AddListener(ProtocolEvent type, EventListenerDelegate listener){AddListener((int)type, listener);}public void RemoveListener(MessageType type, EventListenerDelegate listener){RemoveListener((int)type, listener);}public void RemoveListener(BattleEvent type, EventListenerDelegate listener){RemoveListener((int)type, listener);}public void RemoveListener(ProtocolEvent type, EventListenerDelegate listener){RemoveListener((int)type, listener);}public void SendMessage(MessageType type, params System.Object[] param){SendMessage((int)type, param);}public void SendMessage(BattleEvent type, params System.Object[] param){SendMessage((int)type, param);}public void SendMessage(ProtocolEvent type, params System.Object[] param){SendMessage((int)type, param);}
}

我为每个实现接口的方法又重新封装了3个重载方法,这里主要是为了区分消息的类型,方便更好的维护我们的框架,希望同学们都能养成这样的编写代码习惯。

最后,为了不要再让有人因为跑腿辞职,我们还是用好消息系统,不然他们就要跑去送外卖了

Unity3D基于事件机制的消息系统相关推荐

  1. Atitit.事件机制 与 消息机制的联系与区别

    Atitit.事件机制 与 消息机制的联系与区别 1. 消息/事件机制是几乎所有开发语言都有的机制,在某些语言称之为消息(Event),有些地方称之为(Message).1 2. 发布/订阅模式1 3 ...

  2. 数据传递型情景下事件机制与消息机制的架构设计剖析(目录)

    目录 数据传递型情景下事件机制与消息机制的架构设计剖析(一) 转载于:https://www.cnblogs.com/hailan/p/3616766.html

  3. 快手基于 RocketMQ 的在线消息系统建设实践

    作者:黄理,10 多年软件开发和架构经验,热衷于代码和性能优化,开发和参与过多个开源项目.曾在淘宝任业务架构师多年,当前在快手负责在线消息系统建设工作. 为什么建设在线消息系统 在引入 RocketM ...

  4. 快手基于RocketMQ的在线消息系统建设实践

    简介:快手需要建设一个主要面向在线业务的消息系统作为 Kafka 的补充,低延迟.高并发.高可用.高可靠的分布式消息中间件 RocketMQ 正是我们所需的. 作者:黄理 黄理,10多年软件开发和架构 ...

  5. 基于触发机制的脚本系统

    文 / rooyeewu 1.问题 绝大多数游戏项目都会开发新手引导,剧情之类的功能.这类功能有两个最大的特点:一是跳跃大,二是特殊化.一个完整的功能(如一段教学指引)需要在多个逻辑系统中跳转,并且具 ...

  6. kafka redis vs 发布订阅_发布订阅的消息系统 Kafka的深度解析

    背景介绍 Kafka简介 Kafka是一种分布式的,基于发布/订阅的消息系统.主要设计目标如下: 以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上数据也能保证常数时间的访问性能 高吞吐 ...

  7. 发布订阅的消息系统 Kafka的深度解析

    发布&订阅的消息系统 Kafka的深度解析 2015-01-27 10:25 Jason Guo Jason Guo的博客 字号: T | T 一个典型的kafka集群中包含若干produce ...

  8. 事件触发控制_基于事件触发机制的直流微电网多混合储能系统分层协调控制方法...

    点击下面标题,了解通知详情第九届电工技术前沿问题学术论坛征文通知 华北电力大学电气与电子工程学院的研究人员郭伟.赵洪山,在2020年第5期<电工技术学报>上撰文,以含有多个混合储能系统(H ...

  9. google的api key调用次数是多少_Sprint Boot如何基于Redis发布订阅实现异步消息系统的同步调用?...

    前言 在很多互联网应用系统中,请求处理异步化是提升系统性能一种常用的手段,而基于消息系统的异步处理由于具备高可靠性.高吞吐量的特点,因而在并发请求量比较高的互联网系统中被广泛应用.与此同时,这种方案也 ...

  10. [转]基于SQL Server 2008 Service Broker构建企业级消息系统

    http://www.infoq.com/cn/articles/enterprisemessage-sqlserver-servicebroker 1.引言 Microsoft 在SQL Serve ...

最新文章

  1. poj1679(次小生成树)
  2. C/C++ 函数指针调用函数
  3. iphone开发如何隐藏各种bar
  4. MSBuild编译扩展
  5. VBA合并csv文件
  6. springboot读取src下文件_java(包括springboot)读取resources下文件方式
  7. android开发那些事儿(四)--调用系统相机像素过低
  8. Android 内存监测工具 DDMS -- Heap
  9. 【win10】装机必备推荐软件,提升你的计算机使用效率!
  10. python UI自动化(一)
  11. uniapp企业微信第三方网页授权登录获取code
  12. AngularJS orderBy 使用要点
  13. # Itext Pdf 合并拆分
  14. C#操作word定位光标
  15. 【完美解决方案】Error during artifact deployment. See server log for details.
  16. 需要查询前一次该厂商,料号的单价, 这个sql语句很难写,你碰到过没有
  17. Flutter 中文文档:使用 Packages
  18. dojo学习日记(6)——dojo/_base/fx的 fadeOut()方法
  19. 面向对象OO第一单元三次作业总结
  20. 微信小程序云开发——常用功能2:操作云数据库一键批量导入数据(导入json文件)

热门文章

  1. 哎呀好纠结,到手的感染者数据到底用不用
  2. 区块链能够给物联网带来什么?
  3. 关于电脑的发热问题解决方法
  4. 印度与巨头亚马逊合作,建立量子计算应用实验室
  5. Oracle笔记十七:导入导出
  6. python version cp35,Python wheel的名称中的“ cp3xm”和“ cp2xm”是什么意思?
  7. 浙江计算机高中学校,刚刚,浙江2021年“英才计划”名单公布!这些高中的44名学霸榜上有名!...
  8. WotoKOL卧兔网络:全球品牌出海峰会讲述站外引流技巧,探寻DTC出海流量增长点
  9. 条码软件如何批量制作弧形文字
  10. pycharm terminal 里的一些命令总结