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

相关文章

2. c#从不同cs的文件调用函数

1.文件目录如下: 2. Program.cs文件的主函数如下 using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using System.Windows.Forms;namespace datasAnalysis{internal static

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

用命令行的方式启动.netcore webapi

用命令行的方式启动.netcore web项目 进入指定的项目文件夹,比如我发布后的代码放在下面文件夹中 在此地址栏中输入“cmd”,打开命令提示符,进入到发布代码目录 命令行启动.netcore项目的命令为:  dotnet 项目启动文件.dll --urls="http://*:对外端口" --ip="本机ip" --port=项目内部端口 例: dotnet Imagine.M

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

代码随想录冲冲冲 Day39 动态规划Part7

198. 打家劫舍 dp数组的意义是在第i位的时候偷的最大钱数是多少 如果nums的size为0 总价值当然就是0 如果nums的size为1 总价值是nums[0] 遍历顺序就是从小到大遍历 之后是递推公式 对于dp[i]的最大价值来说有两种可能 1.偷第i个 那么最大价值就是dp[i-2]+nums[i] 2.不偷第i个 那么价值就是dp[i-1] 之后取这两个的最大值就是d

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF