zoukankan      html  css  js  c++  java
  • 依赖注入

      依赖注入(Dependency Injection),是这样一个过程:由于某客户类只依赖于服务类的一个接口,而不依赖于具体服务类,所以客户类只定义一个注入点。在程序运行过程中,客户类不直接实例化具体服务类实例,而是客户类的运行上下文环境或专门组件负责实例化服务类,然后将其注入到客户类中,保证客户类的正常运行。

    一、依赖注入的类别

    1.1 Setter注入

      Setter注入(Setter Injection)是指在客户类中,设置一个服务类接口类型的数据成员,并设置一个Set方法作为注入点,这个Set方法接受一个具体的服务类实例为参数,并将它赋给服务类接口类型的数据成员。

    public interface IServiceClass
    {
      String ServiceInfo();
    }

    public class ServiceClassA : IServiceClass
    {
      public String ServiceInfo()
      {
        return "服务类A";
      }
    }

    public class ServiceClassB : IServiceClass
    {
      public String ServiceInfo()
      {
        return "服务类B";
      }
    }

    public class ClientClass
    {
      private IServiceClass _serviceImp;
      public void Set_ServiceImp(IServiceClass serviceImp)
      {
        this._serviceImp = serviceImp;
      }

      public void ShowInfo()
      {
        Console.WriteLine(_serviceImp.ServiceInfo());
      }
    }

    static void Main(string[] args)
    {
      IServiceClass serviceA = new ServiceClassA();
      IServiceClass serviceB = new ServiceClassB();
      ClientClass client = new ClientClass();

      client.Set_ServiceImp(serviceA);
      client.ShowInfo();
      client.Set_ServiceImp(serviceB);
      client.ShowInfo();
      Console.ReadKey();

    }

    1.2 构造注入

      构造注入(Constructor Injection)是指在客户类中,设置一个服务类接口类型的数据成员,并以构造函数为注入点,这个构造函数接受一个具体的服务类实例为参数,并将它赋给服务类接口类型的数据成员。

    仅ClientClass 和 Content 有变化

    public class ClientClass
    {
      private IServiceClass _serviceImp;

      public ClientClass (IServiceClass serviceImp)

      {
        this._serviceImp = serviceImp;
      }

      public void ShowInfo()
      {
        Console.WriteLine(_serviceImp.ServiceInfo());
      }
    }

    static void Main(string[] args)
    {
      IServiceClass serviceA = new ServiceClassA();
      IServiceClass serviceB = new ServiceClassB();

      ClientClass clientA = new ClientClass(serviceA);
      clientA.ShowInfo();
      ClientClass clientB = new ClientClass(serviceB);
      clientB.ShowInfo();
      Console.ReadKey();

    }

    1.3 依赖获取

      依赖获取(Dependency Locate)是指在系统中提供一个获取点,客户类仍然依赖服务类的接口。当客户类需要服务类时,从获取点主动取得指定的服务类,具体的服务类类型由获取点的配置决定。

     

    二、 反射与依赖注入

      回想上面Dependency Locate的例子,我们虽然使用了多态性和Abstract Factory,但对OCP贯彻的不够彻底。在理解这点前,朋友们一定要注意潜在扩展在哪里,潜在会出现扩展的地方是“新的组件系列”而不是“组件种类”,也就是说,这里我们假设组件就三种,不会增加新的组件,但可能出现新的外观系列,如需要加一套Ubuntu风格的组件,我们可以新增UbuntuWindow、UbuntuButton、UbuntuTextBox和UbuntuFactory,并分别实现相应接口,这是符合OCP的,因为这是扩展。但我们除了修改配置文件,还要无可避免的修改FactoryContainer,需要加一个分支条件,这个地方破坏了OCP。依赖注入本身是没有能力解决这个问题的,但如果语言支持反射机制(Reflection),则这个问题就迎刃而解。

    三、多态的活性与依赖注入

    3.1 多态性的活性

    高活多态性——指在客户类实例运行期间,服务类可能会改变的多态性。

    中活多态性——指在客户类实例化后,服务类不会改变,但同一时间内存在的不同实例可能拥有不同类型的服务类。

    低活多态性——指在客户类实例化后,服务类不会改变,且同一时间内所有客户类都拥有相同类型的服务类。

    3.2 不同活性多态的依赖注入选择

      一般来说,高活多态性适合使用Setter注入。因为Setter注入最灵活,也是唯一允许在同一客户类实例运行期间更改服务类的注入方式。并且这种注入一般由上下文环境通过Setter的参数指定服务类类型,方便灵活,适合频繁变化的高活多态性。

      对于中活多态性,则适合使用Constructor注入。因为Constructor注入也是由上下文环境通过Construtor的参数指定服务类类型,但一点客户类实例化后,就不能进行再次注入,保证了其时间稳定性。

      而对于低活多态性,则适合使用Dependency Locate并配合文件配置进行依赖注入,或Setter、Constructor配合配置文件注入,因为依赖源来自文件,如果要更改服务类,则需要更改配置文件,一则确保了低活多态性的时间和空间稳定性,二是更改配置文件的方式方便于大规模服务类替换。(因为低活多态性一旦改变行为,往往规模很大,如替换整个数据访问层,如果使用Setter和Construtor传参,程序中需要改变的地方不计其数)

    くろさきいちご
  • 相关阅读:
    csuoj-1004-Xi and Bo
    csuoj-1003-UC Browser
    网络命令
    linux网络配置
    java面向对象
    java类 面向对象
    java方法 Scanner、Random类
    java集合
    java数组
    java流程控制语句
  • 原文地址:https://www.cnblogs.com/Andy-Li/p/4950150.html
Copyright © 2011-2022 走看看