• Unity---高度解耦和


    介绍

    先举一个简单的例子:
    在UGUI中新建一个Button和Text,要求实现点击Button改变Text中的文字。
    我的第一反应就是在Button上添加一个脚本,获取点击事件来改变Text的内容。
    或者在Text和Button上都添加一个脚本,Text设置为单例模式,Button点击事件触发Text中的改变文字方法。

    可是这两种方法要不就是关联度太高协作开发时很不好,要不在大项目中用很多单例模式很不好。
    这时就需要到了解耦合技术!!!


    高度解耦合就是利用事件的监听、事件的广播、委托来实现的。

    无参实现

    例如上面点击按钮切换的实现。
    先写3个需要之后调用的类。

    EventType

    //这里面放的是一个枚举类型的事件码,就是用来表示按钮点击事件触发的函数
    public enum EventType
    {
        ShowText,
    }
    

    CallBack

    //这里面放的是所有不同参数类型的委托
    public delegate void CallBack();
    public delegate void CallBack<T>(T arg); 
    

    EventCenter

    using System;
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class EventCenter 
    {
        //定义一个字典存放 事件码 和 委托
        private static Dictionary<EventType, Delegate> m_EventTable = new Dictionary<EventType, Delegate>();
    
    
        //无参的添加事件监听
        public static void AddListener(EventType eventType,CallBack callBack)
        {
    	    //先判断是否包含
            if (!m_EventTable.ContainsKey(eventType))
            {
                m_EventTable.Add(eventType, null);
            }
            //判断要添加的委托和已有的类型是否相同,只有相同才可以添加
            Delegate d = m_EventTable[eventType];  //key为eventType的value
            if (d != null && d.GetType() != callBack.GetType())
            {
                throw new Exception(string.Format("尝试为事件{0}添加不同的委托,当前事件所对应的委托为{1},要添加的委托类型为{2}", eventType, d.GetType(), callBack.GetType()));
    
            }
    
            //要添加的委托和已经存在委托一致了
            //关联一下
            m_EventTable[eventType] =(CallBack) m_EventTable[eventType] + callBack;
        }
        
        //无参的移除监听
        public static void RemoveListener(EventType eventType, CallBack callBack)
        {
            if (m_EventTable.ContainsKey(eventType))
            {
                Delegate d = m_EventTable[eventType];
                if (d == null)   //为空表示事件码没有对应的委托
                {
                    throw new Exception(string.Format("移除监听错误,事件{0}没有对应委托", eventType));
                }
                else if (d.GetType() != callBack.GetType()) //判断委托类型是否一致,一致才能移除
                {
                    throw new Exception(String.Format("移除监听错误,尝试为事件{0}移除不同类型的委托,当前委托类型为{1},要移除的委托类型为{2}", eventType, d.GetType(), callBack.GetType()));
                }
            }
            else //不存在事件码
            {
                throw new Exception(String.Format("移除监听错误,没有事件码{0}", eventType));
            }
    
            //可以移除
            m_EventTable[eventType] = (CallBack)m_EventTable[eventType] - callBack;
    
            if (m_EventTable[eventType] == null) //如果为空了,移除事件码
            {
                m_EventTable.Remove(eventType);
            }
        }
    
        //无参的广播监听
        public static void Broadcast(EventType eventType)
        {
            //把事件码对应的委托取出来,调用一下委托
            Delegate d;
            if(m_EventTable.TryGetValue(eventType,out d)) //尝试获取该键的值
            {
                CallBack callBack = d as CallBack;  //当参数不匹配时会强转失败
                if(callBack != null)
                {
                    callBack();
                }
                else
                {
                    throw new Exception(String.Format("广播事件错误,事件{0}对应委托有不同的类型,", eventType));
                }
            }
        }
    

    ShowText

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    public class ShowText : MonoBehaviour
    {
        //给方法添加监听,设置一个码
        //点击时只需要广播一下事件码
        void Start()
        {
            gameObject.SetActive(false);
            EventCenter.AddListener(EventType.ShowText, Show);  //添加监听
        }
    
        private void OnDestroy()
        {
            EventCenter.RemoveListener(EventType.ShowText, Show);
        }
    
        private void Show()
        {
            gameObject.SetActive(true);
            GetComponent<Text>().text = "Hello";
        }
    }
    

    BtnClick

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class BtnClick : MonoBehaviour
    {
        
        void Start()
        {
    		//Lambda表达式
            GetComponent<Button>().onClick.AddListener(()=>{
                EventCenter.Broadcast(EventType.ShowText); //广播事件
            });
        }
    

    有参和无参基本都是一样的,只是泛型那里添加个类型就好了,不再一一写了

  • 相关阅读:
    n的阶乘
    二叉树遍历
    二分查找练习
    字符串中最长回文序列求解
    复数集合
    AppCrawler自动化遍历使用详解(版本2.1.0 )(转)
    谷歌驱动下载链接
    谷歌浏览器插件
    Pycharm破解方法
    go学习链接
  • 原文地址:https://www.cnblogs.com/Fflyqaq/p/10782574.html
Copyright © 2020-2023  润新知