Sobes.tech
Middle

What implementations of the Inversion of Control (IoC) principle do you know?

sobes.tech AI

Answer from AI

The following implementations are known:

  1. Dependency Lookup:
    The container provides an API for dependency search. The component itself requests the dependencies it needs from the container.

    // Pseudo-code example for Dependency Lookup
    public class SomeService {
        private Dependency dependency;
    
        public SomeService() {
            // The component searches for the dependency from the container
            this.dependency = IoCContainer.getDependency("myDependency");
        }
    
        public void doSomething() {
            dependency.performAction();
        }
    }
    
  2. Dependency Injection (DI):
    The container injects dependencies into the component itself. There are several forms of DI:

    • Constructor Injection: Dependencies are passed through the constructor. This is the preferred method as it makes dependencies explicit and mandatory.

      // Constructor Injection example
      public class OtherService {
          private final AnotherDependency anotherDependency;
      
          // Dependency is injected through the constructor
          public OtherService(AnotherDependency anotherDependency) {
              this.anotherDependency = anotherDependency;
          }
      
          public void doSomethingElse() {
              anotherDependency.someOperation();
          }
      }
      
    • Setter Injection: Dependencies are passed through setter methods. It allows dependencies to be optional or changed after object creation.

      // Setter Injection example
      public class YetAnotherService {
          private LastDependency lastDependency;
      
          // Dependency is injected through a setter
          public void setLastDependency(LastDependency lastDependency) {
              this.lastDependency = lastDependency;
          }
      
          public void andAnotherThing() {
              // Check if the dependency is set
              if (lastDependency != null) {
                  lastDependency.lastMethod();
              }
          }
      }
      
    • Field Injection: Dependencies are injected directly into class fields using annotations (e.g., @Autowired in Spring). This is the simplest syntactically but the least recommended way, as it hides dependencies and complicates testing.

      // Field Injection example (using Spring)
      // Assume LastDependency is a Spring Bean
      import org.springframework.beans.factory.annotation.Autowired;
      
      public class FieldInjectedService {
          // Dependency is injected directly into the field
          @Autowired
          private LastDependency lastDependency;
      
          public void finalAction() {
              lastDependency.lastMethod();
          }
      }
      

Comparison table of main forms of Dependency Injection:

DI Form Advantages Disadvantages Usage Recommendations
Constructor Dependencies are explicit and mandatory; easier testing; guarantees object integrity. Impossible to create cyclic dependencies without additional mechanisms; many constructor parameters may indicate SRP violation. Preferred for mandatory dependencies.
Setter Allows setting optional dependencies; dependencies can be changed after object creation. Dependencies are implicit; the object may be in an incomplete or incorrect state before all dependencies are set. For optional dependencies; sometimes to avoid cyclic dependencies.
Field (@Autowired) The least verbose code. Hides dependencies; complicates unit testing; violates OOP principles (e.g., encapsulation). Generally not recommended; may be used in small applications or demos.
What implementations of the Inversion of Control… - sobes.tech