Unity框架学习--2

这篇具有很好参考价值的文章主要介绍了Unity框架学习--2。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

接上文

IOC 容器是一个很方便的模块管理工具。

除了可以用来注册和获取模块,IOC 容器一般还会有一个隐藏的功能,即:

注册接口模块

抽象-实现 这种形式注册和获取对象的方式是符合依赖倒置原则的。

依赖倒置原则(Dependence Inversion Principle):程序要依赖于抽象接口,不要依赖于具体实现。

好处如下:

  • 接口设计与实现分成两个步骤,接口设计时可以专注于设计,实现时可以专注于实现。
  • 接口设计时专注于设计可以减少系统设计时的干扰。
  • 实现是可以替换的,比如一个接口叫 IStorage,其实现可以是 PlayerPrefsStorage、EasySaveStorage、EdtiroPrefsStorage,等切换时候只需要一行代码就可以切换了。
  • 比较容易测试(单元测试等)
  • 当实现细节(比如 PlayerPrefsStorage)发生变化时,其引用接口(比如 IStorage)类里的代码不会跟着改变,降低耦合。
  • 等等

支持数据存储

接口的阉割技术

利用 C# 接口的显示实现,来达到接口方法在子类阉割的目的,而要想调用这个方法必须通过接口而不是方法所在的对象。

using UnityEngine;

namespace FrameworkDesign.Example
{
    /// <summary>
    /// 1. 定义接口
    /// </summary>
    public interface ICanSayHello
    {
        void SayHello();
        void SayOther();
    }
    
    public class InterfaceDesignExample : MonoBehaviour,ICanSayHello
    {
        /// <summary>
        /// 接口的隐式实现
        /// </summary>
        public void SayHello()
        {
            Debug.Log("Hello");
        }

        /// <summary>
        /// 接口的显式实现
        /// </summary>
        void ICanSayHello.SayOther()
        {
            Debug.Log("Other");
        }
        
        // Start is called before the first frame update
        void Start()
        {
            // 隐式实现的方法可以直接通过对象调用
            this.SayHello();
            
            // 显式实现的接口不能通过对象调用
            // this.SayOther() // 会报编译错误
            
            // 显式实现的接口必须通过接口对象调用
            (this as ICanSayHello).SayOther();
        }
    }
}

 // 显式实现的方法必须通过接口对象调用
            (this as ICanSayHello).SayOther();

如果要想调用一个对象的显式实现的方法,那么必须要将此对象强制转换成接口对象才能调用,这样就增加了调用显式实现的方法的成本,所以可以理解为这个方法被阉割了。

使用案例 1  接口-抽象类-实现类的结构

第一种就是比较常见的 接口-抽象类-实现类的结构,示例代码如下:
using UnityEngine;

namespace FrameworkDesign.Example
{
    public class InterfaceStructExample : MonoBehaviour
    {
        /// <summary>
        /// 接口
        /// </summary>
        public interface ICustomScript
        {
            void Start();
            void Update();
            void Destroy();
        }
        
        /// <summary>
        /// 抽象类
        /// </summary>
        public abstract class CustomScript : ICustomScript
        {
            protected bool mStarted { get; private set; }
            protected bool mDestroyed { get; private set; }
            
            /// <summary>
            /// 不希望子类访问 Start 方法,因为有可能破坏状态
            /// </summary>
            void ICustomScript.Start()
            {
                OnStart();
                mStarted = true;
            }
            
            void ICustomScript.Update()
            {
               OnUpdate();
            }

            void ICustomScript.Destroy()
            {
                OnDestroy();
                mDestroyed = true;
            }
            
            /// <summary>
            /// 希望子类实现 OnStart 方法
            /// </summary>
            protected abstract void OnStart();
            protected abstract void OnUpdate();
            protected abstract void OnDestroy();
        }
        
        /// <summary>
        /// 由用户扩展的类
        /// </summary>
        public class MyScript : CustomScript
        {
            protected override void OnStart()
            {
                Debug.Log("MyScript:OnStart");
            }

            protected override void OnUpdate()
            {
                Debug.Log("MyScript:OnUpdate");
            }

            protected override void OnDestroy()
            {
                Debug.Log("MyScript:OnDestroy");
            }
        }

        /// <summary>
        /// 测试脚本
        /// </summary>
        private void Start()
        {
            ICustomScript script = new MyScript();
            script.Start();
            script.Update();
            script.Destroy();
        }
    }
}

第二个使用案例     接口 + 扩展时用于限制方法的访问规则

using UnityEngine;

namespace FrameworkDesign.Example
{
    public class CanDoEveryThing 
    {
        public void DoSomething1()
        {
            Debug.Log("DoSomething1");
        }

        public void DoSomething2()
        {
            Debug.Log("DoSomething2");
        }

        public void DoSomething3()
        {
            Debug.Log("DoSomething3");
        }
    }

    public interface IHasEveryThing
    {
        CanDoEveryThing CanDoEveryThing { get; }
    }

    public interface ICanDoSomething1 : IHasEveryThing
    {
        
    }

    public static class ICanDoSomeThing1Extensions
    {
        public static void DoSomething1(this ICanDoSomething1 self)
        {
            self.CanDoEveryThing.DoSomething1();
        }
    }

    public interface ICanDoSomething2 : IHasEveryThing
    {
        
    }
    
    public static class ICanDoSomeThing2Extensions
    {
        public static void DoSomething2(this ICanDoSomething2 self)
        {
            self.CanDoEveryThing.DoSomething2();
        }
    }

    public interface ICanDoSomething3 : IHasEveryThing
    {

    }
    
    public static class ICanDoSomeThing3Extensions
    {
        public static void DoSomething3(this ICanDoSomething3 self)
        {
            self.CanDoEveryThing.DoSomething3();
        }
    }

    public class InterfaceRuleExample : MonoBehaviour
    {
        public class OnlyCanDo1 : ICanDoSomething1
        {
            CanDoEveryThing IHasEveryThing.CanDoEveryThing { get; } = new CanDoEveryThing();
        }
        
        public class OnlyCanDo23 : ICanDoSomething2,ICanDoSomething3
        {
            CanDoEveryThing IHasEveryThing.CanDoEveryThing { get; } = new CanDoEveryThing();
        }

        private void Start()
        {
            var onlyCanDo1 = new OnlyCanDo1();
            // 可以调用 DoSomething1
            onlyCanDo1.DoSomething1();
            // 不能调用 DoSomething2 和 3 会报编译错误
            // onlyCanDo1.DoSomething2();
            // onlyCanDo1.DoSomething3();


            var onlyCanDo23 = new OnlyCanDo23();
            // 不可以调用 DoSomething1 会报编译错误
            // onlyCanDo23.DoSomething1();
            // 可以调用 DoSomething2 和 3
            onlyCanDo23.DoSomething2();
            onlyCanDo23.DoSomething3();
        }
    }
}

总结一下:文章来源地址https://www.toymoban.com/news/detail-647648.html

  • 接口的阉割技术核心的知识是接口的显式实现
  • 接口+抽象类+具体类 时,不想被乱调用一些方法时可以用接口阉割技术。
  • 接口+静态扩展时,想要通过实现某个接口来获得具体方法的访问权限时可以用接口阉割技术。

到了这里,关于Unity框架学习--2的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity框架学习--资源管理器

    1、Inspector窗口拖拽         在脚本中用public声明变量,然后在Inspector窗口把要加载的资源拖拽给该脚本的变量。         不建议在大型项目使用。在公司的项目也不要用。         如果你是独立游戏开发者,则可以用。         不支持热更新。 2、Resources         用Reso

    2024年02月12日
    浏览(25)
  • Unity框架学习--5 事件中心管理器

    作用 :访问其它脚本时,不直接访问,而是通过发送一条“命令”,让监听了这条“命令”的脚本自动执行对应的逻辑。 原理: 1、让脚本向事件中心添加事件,监听对应的“命令”。 2、发送“命令”,事件中心就会通知监听了这条“命令”的脚本,让它们自动执行对应的

    2024年02月13日
    浏览(16)
  • Unity框架学习--4 Mono管理器

    作用 :使不继承MonoBehaviour的类能够开启协程,并且可以使用FixedUpdate、Update、LateUpdate进行每帧更新。 原理: 1、在场景中创建一个继承MonoBehaviour的“执行者”脚本,这个脚本就专门用来开启协程和监听帧更新。 2、Mono管理器访问这个“执行者”脚本,就可以实现所需的效果

    2024年02月13日
    浏览(18)
  • Unity框架设计系列:Unity 如何设计网络框架

    在Unity框架设计中与游戏服务器对接的网络框架也是非常重要的一个模块,本文給大家分享如何来基于Unity来设计一个网络框架, 主要的讲解以下几个点: 这里有个游戏开发交流小组 大家可以一起学习交流 (1) TCP半包粘包, 长连接与短连接, IO阻塞; (2) Tcp Socket与UDP Socket 的技术方

    2023年04月23日
    浏览(21)
  • 【Unity 框架】QFramework v1.0 使用指南 架构篇:03. 引入 Command | Unity 游戏框架 | Unity 游戏开发 | Unity 独立游戏

    我们回顾一下目前的代码,如下; 现在,数据共享的问题通过 引入 Model 解决了。 这里再次强调一下,需要共享的数据放 Model 里,不需要共享的,能不放就不放。 虽然引入了 Model,但是这套代码随着项目规模的发展还是有很多的问题。 其中最严重也最常见的就是 Controller

    2024年02月06日
    浏览(31)
  • 【Unity 框架】QFramework v1.0 使用指南 工具篇:13. 其他事件工具 | Unity 游戏框架 | Unity 游戏开发 | Unity 独立游戏

    QFramework 除了支持了 TypeEventSystem、EasyEvent 还支持了 EnumEventSystem、StringEventSystem。 EnumEventSystem 前身是 老版本 QFramework 的 QEventSystem StringEventSystem 的前身是,老版本的 MsgDispatcher TypeEventSystem: 事件体定义简洁 比较适合用于设计框架 支持 struct 获得较好内存性能 使用反射,CPU

    2023年04月17日
    浏览(38)
  • Unity技术框架集合、Unity技术栈汇总

    引擎技术尝试 [Animancer-Pro] (https://assetstore.unity.com/packages/tools/animation/animancer-pro-116514) (基于Playable的简单强大的动画解决方案) [ProBuilder/UModeler] (https://assetstore.unity.com/packages/tools/modeling/umodeler-80868) (快速关卡原型构建解决方案) [FGUI] (

    2024年02月14日
    浏览(18)
  • 【Unity 框架】QFramework v1.0 使用指南 工具篇:05. ResKit 资源管理&开发解决方案 | Unity 游戏框架 | Unity 游戏开发 | Unity 独立游戏

    Res Kit,是资源管理快速开发解决方案 特性如下: 可以使用一个 API 从 dataPath、Resources、StreammingAssetPath、PersistentDataPath、网络等地方加载资源。 基于引用计数,简化资源加载和卸载。 拥抱游戏开发流程中的不同阶段 开发阶段不用打 AB 直接从 dataPath 加载。 测试阶段支持只需打

    2024年02月01日
    浏览(29)
  • Unity实用框架(一)场景管理框架

    众所周知,Unity引擎本身提供了具有切换场景功能的SceneManager模块,但只包含比较基础的功能,比如简单的切换场景、创建场景等,想要使得我们的场景管理框架能够适用于更加复杂的情形,显然需要一套更加强大的接口。下面,笔者将提供一种撰写灵活好用的SceneManager的可

    2023年04月09日
    浏览(13)
  • Unity常见框架探索-ET框架探索

    简介 ET框架是类ECS的一个Unity前后端框架 论坛地址为:https://et-framework.cn Git地址为:https://github.com/egametang/ET Unity程序集的使用 本文将会以7.2版本进行分析。所以直接clone github上的仓库,将工程导入到本地,之后将分支切换到最新的release分支,\\\"release7.2\\\" ET-ChangeDefine-ADD_ENABLE

    2024年02月09日
    浏览(21)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包