Aprendizaje del marco de Unity--2

Continuar desde arriba

El contenedor IOC es una herramienta de gestión de módulos muy conveniente.

Además de usarse para registrar y obtener módulos, los contenedores IOC generalmente tienen una función oculta, a saber:

Registrar módulo de interfaz

Abstracción: la forma en que se implementa esta forma de registrar y recuperar objetos es consistente con el principio de inversión de dependencia .

Principio de inversión de dependencia: los programas deben depender de interfaces abstractas, no de implementaciones concretas.

Los beneficios son los siguientes:

  • El diseño y la implementación de la interfaz se dividen en dos pasos: al diseñar la interfaz, puede concentrarse en el diseño y al implementarla, puede concentrarse en la implementación.
  • Centrarse en el diseño al diseñar la interfaz puede reducir la interferencia durante el diseño del sistema.
  • La implementación se puede reemplazar. Por ejemplo, si una interfaz se llama IStorage, su implementación puede ser PlayerPrefsStorage, EasySaveStorage o EdtiroPrefsStorage. Al cambiar, solo se necesita una línea de código para cambiar.
  • Más fácil de probar (pruebas unitarias, etc.)
  • Cuando los detalles de implementación (como PlayerPrefsStorage) cambian, el código en su clase de interfaz de referencia (como IStorage) no cambiará en consecuencia, lo que reduce el acoplamiento.
  • etc.

Almacenamiento de datos de soporte

Tecnología de castración de interfaz.

La implementación explícita de la interfaz C# se utiliza para lograr el propósito de castrar el método de la interfaz en la subclase. Si desea llamar a este método, debe pasar la interfaz en lugar del objeto donde se encuentra el método.

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();
        }
    }
}

 // Los métodos implementados explícitamente deben llamarse a través del objeto de interfaz
             ( esto  es  ICanSayHello ). SayOther ();

Si desea llamar al método implementado explícitamente de un objeto, debe convertir el objeto en un objeto de interfaz antes de llamarlo, lo que aumenta el costo de llamar al método implementado explícitamente, por lo que se puede entender que este método ha sido castrado.

Caso de uso 1 interfaz-clase abstracta-estructura de clase de implementación

第一种就是比较常见的 接口-抽象类-实现类的结构,示例代码如下:
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();
        }
    }
}

Interfaz del segundo caso de uso + reglas de acceso para restringir métodos al extender

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();
        }
    }
}

en conclusión:

  • El conocimiento central de la tecnología de castración de interfaz es la implementación explícita de la interfaz.
  • Cuando usa interfaz + clase abstracta + clase concreta, puede usar la tecnología de castración de interfaz si no desea que algunos métodos se llamen aleatoriamente.
  • Cuando utilice interfaz + extensión estática, puede utilizar la tecnología de castración de interfaz cuando desee obtener acceso a métodos específicos mediante la implementación de una interfaz.

Supongo que te gusta

Origin blog.csdn.net/zaizai1007/article/details/132263349
Recomendado
Clasificación