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

相关文章

python使用Akshare与Streamlit实现股票估值分析教程(图文代码)

《python使用Akshare与Streamlit实现股票估值分析教程(图文代码)》入职测试中的一道题,要求:从Akshare下载某一个股票近十年的财务报表包括,资产负债表,利润表,现金流量表,保存... 目录一、前言二、核心知识点梳理1、Akshare数据获取2、Pandas数据处理3、Matplotl

Django开发时如何避免频繁发送短信验证码(python图文代码)

《Django开发时如何避免频繁发送短信验证码(python图文代码)》Django开发时,为防止频繁发送验证码,后端需用Redis限制请求频率,结合管道技术提升效率,通过生产者消费者模式解耦业务逻辑... 目录避免频繁发送 验证码1. www.chinasem.cn避免频繁发送 验证码逻辑分析2. 避免频繁

精选20个好玩又实用的的Python实战项目(有图文代码)

《精选20个好玩又实用的的Python实战项目(有图文代码)》文章介绍了20个实用Python项目,涵盖游戏开发、工具应用、图像处理、机器学习等,使用Tkinter、PIL、OpenCV、Kivy等库... 目录① 猜字游戏② 闹钟③ 骰子模拟器④ 二维码⑤ 语言检测⑥ 加密和解密⑦ URL缩短⑧ 音乐播放

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

C#中lock关键字的使用小结

《C#中lock关键字的使用小结》在C#中,lock关键字用于确保当一个线程位于给定实例的代码块中时,其他线程无法访问同一实例的该代码块,下面就来介绍一下lock关键字的使用... 目录使用方式工作原理注意事项示例代码为什么不能lock值类型在C#中,lock关键字用于确保当一个线程位于给定实例的代码块中时

C# $字符串插值的使用

《C#$字符串插值的使用》本文介绍了C#中的字符串插值功能,详细介绍了使用$符号的实现方式,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录$ 字符使用方式创建内插字符串包含不同的数据类型控制内插表达式的格式控制内插表达式的对齐方式内插表达式中使用转义序列内插表达式中使用

C#中的Converter的具体应用

《C#中的Converter的具体应用》C#中的Converter提供了一种灵活的类型转换机制,本文详细介绍了Converter的基本概念、使用场景,具有一定的参考价值,感兴趣的可以了解一下... 目录Converter的基本概念1. Converter委托2. 使用场景布尔型转换示例示例1:简单的字符串到

Python Web框架Flask、Streamlit、FastAPI示例详解

《PythonWeb框架Flask、Streamlit、FastAPI示例详解》本文对比分析了Flask、Streamlit和FastAPI三大PythonWeb框架:Flask轻量灵活适合传统应用... 目录概述Flask详解Flask简介安装和基础配置核心概念路由和视图模板系统数据库集成实际示例Stre

C#监听txt文档获取新数据方式

《C#监听txt文档获取新数据方式》文章介绍通过监听txt文件获取最新数据,并实现开机自启动、禁用窗口关闭按钮、阻止Ctrl+C中断及防止程序退出等功能,代码整合于主函数中,供参考学习... 目录前言一、监听txt文档增加数据二、其他功能1. 设置开机自启动2. 禁止控制台窗口关闭按钮3. 阻止Ctrl +

C#解析JSON数据全攻略指南

《C#解析JSON数据全攻略指南》这篇文章主要为大家详细介绍了使用C#解析JSON数据全攻略指南,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、为什么jsON是C#开发必修课?二、四步搞定网络JSON数据1. 获取数据 - HttpClient最佳实践2. 动态解析 - 快速