Aprendizagem da estrutura do Unity - 2

Continuar de cima

O contêiner IOC é uma ferramenta de gerenciamento de módulo muito conveniente.

Além de serem utilizados para registrar e obter módulos, os contêineres IOC geralmente possuem uma função oculta, a saber:

Registrar módulo de interface

Abstração - A forma como esta forma de registro e recuperação de objetos é implementada é consistente com o princípio de inversão de dependências .

Princípio de Inversão de Dependência: Os programas devem depender de interfaces abstratas, não de implementações concretas.

Os benefícios são os seguintes:

  • O design e a implementação da interface são divididos em duas etapas: ao projetar a interface, você pode se concentrar no design e, ao implementá-la, pode se concentrar na implementação.
  • Concentrar-se no design ao projetar a interface pode reduzir a interferência durante o projeto do sistema.
  • A implementação pode ser substituída. Por exemplo, se uma interface for chamada IStorage, sua implementação pode ser PlayerPrefsStorage, EasySaveStorage ou EdtiroPrefsStorage. Ao alternar, apenas uma linha de código é necessária para alternar.
  • Mais fácil de testar (testes de unidade, etc.)
  • Quando os detalhes da implementação (como PlayerPrefsStorage) mudam, o código em sua classe de interface de referência (como IStorage) não muda de acordo, reduzindo o acoplamento.
  • etc.

Suporte para armazenamento de dados

Tecnologia de castração de interface

A implementação explícita da interface C# é usada para atingir o objetivo de castrar o método de interface na subclasse. Se você quiser chamar esse método, deverá passar a interface em vez do objeto onde o método está localizado.

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

 // Métodos explicitamente implementados devem ser chamados através do objeto de interface
             ( isto  como  ICanSayHello ) .SayOther ();

Se você quiser chamar um método explicitamente implementado de um objeto, você deve converter o objeto em um objeto de interface antes de chamá-lo. Isso aumenta o custo de chamar o método explicitamente implementado, para que possa ser entendido que este método foi castrado.

Caso de uso 1 estrutura de classe de implementação de classe abstrata de interface

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

Interface do segundo caso de uso + regras de acesso para restringir métodos ao estender

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

para concluir:

  • O conhecimento central da tecnologia de castração de interface é a implementação explícita da interface
  • Ao usar interface + classe abstrata + classe concreta, você pode usar a tecnologia de castração de interface se não quiser que alguns métodos sejam chamados aleatoriamente.
  • Ao usar interface + extensão estática, você pode usar a tecnologia de castração de interface quando quiser obter acesso a métodos específicos implementando uma interface.

Acho que você gosta

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