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

18 篇文章 5 订阅
1 篇文章 0 订阅

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

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

   话不多说,直接上代码。

   消息分发中心:

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 消息相关

    //需注册的消息. TODO
    private 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);
        }
    }

    //收到消息的回调 TODO
    private 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


}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值