订阅发布者模式/观察者模式-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

相关文章

C#实现千万数据秒级导入的代码

《C#实现千万数据秒级导入的代码》在实际开发中excel导入很常见,现代社会中很容易遇到大数据处理业务,所以本文我就给大家分享一下千万数据秒级导入怎么实现,文中有详细的代码示例供大家参考,需要的朋友可... 目录前言一、数据存储二、处理逻辑优化前代码处理逻辑优化后的代码总结前言在实际开发中excel导入很

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

C#实现一键批量合并PDF文档

《C#实现一键批量合并PDF文档》这篇文章主要为大家详细介绍了如何使用C#实现一键批量合并PDF文档功能,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言效果展示功能实现1、添加文件2、文件分组(书签)3、定义页码范围4、自定义显示5、定义页面尺寸6、PDF批量合并7、其他方法

C#下Newtonsoft.Json的具体使用

《C#下Newtonsoft.Json的具体使用》Newtonsoft.Json是一个非常流行的C#JSON序列化和反序列化库,它可以方便地将C#对象转换为JSON格式,或者将JSON数据解析为C#对... 目录安装 Newtonsoft.json基本用法1. 序列化 C# 对象为 JSON2. 反序列化

GSON框架下将百度天气JSON数据转JavaBean

《GSON框架下将百度天气JSON数据转JavaBean》这篇文章主要为大家详细介绍了如何在GSON框架下实现将百度天气JSON数据转JavaBean,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录前言一、百度天气jsON1、请求参数2、返回参数3、属性映射二、GSON属性映射实战1、类对象映

C#文件复制异常:"未能找到文件"的解决方案与预防措施

《C#文件复制异常:未能找到文件的解决方案与预防措施》在C#开发中,文件操作是基础中的基础,但有时最基础的File.Copy()方法也会抛出令人困惑的异常,当targetFilePath设置为D:2... 目录一个看似简单的文件操作问题问题重现与错误分析错误代码示例错误信息根本原因分析全面解决方案1. 确保

Redis实现高效内存管理的示例代码

《Redis实现高效内存管理的示例代码》Redis内存管理是其核心功能之一,为了高效地利用内存,Redis采用了多种技术和策略,如优化的数据结构、内存分配策略、内存回收、数据压缩等,下面就来详细的介绍... 目录1. 内存分配策略jemalloc 的使用2. 数据压缩和编码ziplist示例代码3. 优化的

基于C#实现PDF转图片的详细教程

《基于C#实现PDF转图片的详细教程》在数字化办公场景中,PDF文件的可视化处理需求日益增长,本文将围绕Spire.PDFfor.NET这一工具,详解如何通过C#将PDF转换为JPG、PNG等主流图片... 目录引言一、组件部署二、快速入门:PDF 转图片的核心 C# 代码三、分辨率设置 - 清晰度的决定因