订阅发布者模式/观察者模式-Unity C#代码框架

2023-12-20 17:18

本文主要是介绍订阅发布者模式/观察者模式-Unity C#代码框架,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

    什么是订阅发布者模式?简单的说,比如我看见有人在公交车上偷钱包,于是大叫一声“有人偷钱包”(发送消息),车上的人听到(接收到消息)后做出相应的反应,比如看看自己的钱包什么的。其实就两个步骤,注册消息与发送消息。

    为了适应项目需要,写了一个通用订阅发布者模式的通用模块,有了这样一个模块,项目里面其他模块之间的耦合性也将大大降低。

   话不多说,直接上代码。

   消息分发中心:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 消息分发中心.
/// </summary>
public class DispatcherCenter
{private static Logger logger = LogHelper.GetLogger("DispatcerCenter");private static DispatcherCenter instance;public static DispatcherCenter Instance{get{if (instance == null){instance = new DispatcherCenter();}return instance;}}private Dictionary<int, List<Observer>> map = new Dictionary<int, List<Observer>>();/// <summary>/// 发送消息./// </summary>/// <param name="type">消息类型.</param>/// <param name="msg">消息内容.</param>public void SendNotification(int type, object msg){if (map.ContainsKey(type)){List<Observer> observers = map[type];foreach (Observer obs in observers){Notification notice = new Notification(type, msg);if(obs.handler != null){obs.handler(notice);}}}else{if (msg == null){logger.Error("分发消息失败,未注册该消息!!! Type: " + type + " Msg is null.");}else{logger.Error("分发消息失败,未注册该消息!!! Type: " + type + " Msg: " + msg);}}}/// <summary>/// 注册消息./// </summary>/// <param name="type">消息类型.</param>/// <param name="handler">收到消息的回调.</param>public void RegisterObserver(int type, NotificationHandler handler){List<Observer> observers = null;if (map.TryGetValue(type, out observers)){foreach (Observer obs in observers){if (obs.handler == handler){//logger.Debug("该回调已经注册,不能重复注册!");return;}}observers.Add(new Observer(type, handler));}else{observers = new List<Observer>();observers.Add(new Observer(type, handler));map.Add(type, observers);}}/// <summary>/// 移除消息./// </summary>/// <param name="type">消息类型.</param>/// <param name="handler">收到消息的回调.</param>public void RemoveObserver(int type, NotificationHandler handler){List<Observer> observers = map[type];if (map.TryGetValue(type, out observers)){foreach (Observer obs in observers){if(obs.handler == handler){observers.Remove(obs);//bool result = observers.Remove(obs);//logger.Debug("消息移除是否成功: " + result);return;}}logger.Error("移除失败,未找到该回调!!! Type: " + type);}else{logger.Error("移除失败,未注册该消息!!! Type: " + type);}}
}

 订阅者:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;//接收到消息的回调.
public delegate void NotificationHandler(Notification notice);/// <summary>
/// 观察者.
/// </summary>
public class Observer
{public NotificationHandler handler;public Observer() { }public Observer(int type, NotificationHandler handler){this.handler += handler;}
}

消息类:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 消息类.
/// </summary>
public class Notification
{private int type;private object msg;public int Type { get { return type; } }public object Msg { get { return msg; } }public Notification(int type, object msg){this.type = type;this.msg = msg;}public override string ToString(){if (msg != null){return string.Format("Type:{0} Msg:{1}", type, msg.ToString());}return string.Format("Type:{0} Msg is null", type);}
}

消息:(我用的是枚举表示,然后强转为int值来识别是哪个消息,枚举值不能重复)

/// <summary>
/// 消息枚举.
/// </summary>
public class NotificationEnum
{public enum ModelNotices{SEPARATE = 0,MERGE}public enum OtherNotice{OTHER1 = 101,OTHER2}
}

那么如何使用呢?

还是看代码,首先在Notifications中添加要注册的消息号,然后在合适时候调用RegisterNotifications()注册消息,在NotificationHandler()中根据消息号做出相应的操作。在不需要再观察消息的时候移除消息RemoveNotifications();

using UnityEngine;public class Test : MonoBehaviour
{private void Awake(){RegisterNotifications();}private void OnDestory(){RemoveNotifications();}private void Update(){if (Input.GetKeyDown(KeyCode.F1)){UnityEngine.Debug.Log("---------->>>> 分离消息.");//消息内容可以是任何东西,如int值,类    DispatcherCenter.Instance.SendNotification((int)NotificationEnum.ModelNotices.SEPARATE, null);}if (Input.GetKeyDown(KeyCode.F2)){UnityEngine.Debug.Log("---------->>>> 合并消息.");//消息内容可以是任何东西,如int值,类            DispatcherCenter.Instance.SendNotification((int)NotificationEnum.ModelNotices.MERGE, null);}//if (Input.GetKeyDown(KeyCode.F1))//{//    Debug.Log("Test1 注册消息.");//    RegisterNotifications();//}//if (Input.GetKeyDown(KeyCode.Keypad1))//{//    Debug.Log("Test1 移除消息.");//    RemoveNotifications();//}}#region 消息相关//需注册的消息. TODOprivate int[] Notifications{get{return new int[]{(int)NotificationEnum.ModelNotices.SEPARATE,(int)NotificationEnum.ModelNotices.MERGE};}}private void RegisterNotifications(){for (int i = 0; i < Notifications.Length; i++){DispatcherCenter.Instance.RegisterObserver(Notifications[i], NotificationHandler);}}private void RemoveNotifications(){for (int i = 0; i < Notifications.Length; i++){DispatcherCenter.Instance.RemoveObserver(Notifications[i], NotificationHandler);}}//收到消息的回调 TODOprivate void NotificationHandler(Notification notice){if (notice.Type == (int)NotificationEnum.ModelNotices.SEPARATE){UnityEngine.Debug.Log("Test1收到零件分离的消息." + notice.ToString());}else if (notice.Type == (int)NotificationEnum.ModelNotices.MERGE){UnityEngine.Debug.Log("Test1收到零件合并的消息." + notice.ToString());}}#endregion}

 

这篇关于订阅发布者模式/观察者模式-Unity C#代码框架的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/516819

相关文章

基于 HTML5 Canvas 实现图片旋转与下载功能(完整代码展示)

《基于HTML5Canvas实现图片旋转与下载功能(完整代码展示)》本文将深入剖析一段基于HTML5Canvas的代码,该代码实现了图片的旋转(90度和180度)以及旋转后图片的下载... 目录一、引言二、html 结构分析三、css 样式分析四、JavaScript 功能实现一、引言在 Web 开发中,

Python如何去除图片干扰代码示例

《Python如何去除图片干扰代码示例》图片降噪是一个广泛应用于图像处理的技术,可以提高图像质量和相关应用的效果,:本文主要介绍Python如何去除图片干扰的相关资料,文中通过代码介绍的非常详细,... 目录一、噪声去除1. 高斯噪声(像素值正态分布扰动)2. 椒盐噪声(随机黑白像素点)3. 复杂噪声(如伪

Java Spring ApplicationEvent 代码示例解析

《JavaSpringApplicationEvent代码示例解析》本文解析了Spring事件机制,涵盖核心概念(发布-订阅/观察者模式)、代码实现(事件定义、发布、监听)及高级应用(异步处理、... 目录一、Spring 事件机制核心概念1. 事件驱动架构模型2. 核心组件二、代码示例解析1. 事件定义

Redis Cluster模式配置

《RedisCluster模式配置》:本文主要介绍RedisCluster模式配置,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录分片 一、分片的本质与核心价值二、分片实现方案对比 ‌三、分片算法详解1. ‌范围分片(顺序分片)‌2. ‌哈希分片3. ‌虚

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部

Java中Map.Entry()含义及方法使用代码

《Java中Map.Entry()含义及方法使用代码》:本文主要介绍Java中Map.Entry()含义及方法使用的相关资料,Map.Entry是Java中Map的静态内部接口,用于表示键值对,其... 目录前言 Map.Entry作用核心方法常见使用场景1. 遍历 Map 的所有键值对2. 直接修改 Ma

C#如何去掉文件夹或文件名非法字符

《C#如何去掉文件夹或文件名非法字符》:本文主要介绍C#如何去掉文件夹或文件名非法字符的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#去掉文件夹或文件名非法字符net类库提供了非法字符的数组这里还有个小窍门总结C#去掉文件夹或文件名非法字符实现有输入字

C#之List集合去重复对象的实现方法

《C#之List集合去重复对象的实现方法》:本文主要介绍C#之List集合去重复对象的实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C# List集合去重复对象方法1、测试数据2、测试数据3、知识点补充总结C# List集合去重复对象方法1、测试数据

C#实现将Office文档(Word/Excel/PDF/PPT)转为Markdown格式

《C#实现将Office文档(Word/Excel/PDF/PPT)转为Markdown格式》Markdown凭借简洁的语法、优良的可读性,以及对版本控制系统的高度兼容性,逐渐成为最受欢迎的文档格式... 目录为什么要将文档转换为 Markdown 格式使用工具将 Word 文档转换为 Markdown(.

Java调用C#动态库的三种方法详解

《Java调用C#动态库的三种方法详解》在这个多语言编程的时代,Java和C#就像两位才华横溢的舞者,各自在不同的舞台上展现着独特的魅力,然而,当它们携手合作时,又会碰撞出怎样绚丽的火花呢?今天,我们... 目录方法1:C++/CLI搭建桥梁——Java ↔ C# 的“翻译官”步骤1:创建C#类库(.NET