Sobes.tech
Junior — Middle

How to eliminate cyclic references between classes caused by mutual dependency injection?

sobes.tech AI

Answer from AI

Cyclic dependencies between classes in mutual dependency injection lead to initialization problems and complicate code maintenance.

Ways to resolve:

  1. Refactoring architecture:

    • Separate responsibilities, define interfaces.
    • Introduce a third class or service to coordinate interactions.
  2. Using lazy initialization or providers:

    • Inject dependencies through factories or providers that create objects on demand.
  3. Applying events or callbacks:

    • Use the Observer pattern or events for interaction instead of direct references.
  4. Inversion of Control (IoC) and dependency containers:

    • Containers can resolve cycles by creating proxies or lazy objects.

Example:

// Interfaces
interface ServiceA {
    void doA();
}

interface ServiceB {
    void doB();
}

// Implementation breaking the cycle via interface
class ServiceAImpl implements ServiceA {
    private ServiceB serviceB;

    public ServiceAImpl(ServiceB serviceB) {
        this.serviceB = serviceB;
    }

    public void doA() {
        // ...
        serviceB.doB();
    }
}

class ServiceBImpl implements ServiceB {
    private ServiceA serviceA;

    public void setServiceA(ServiceA serviceA) {
        this.serviceA = serviceA;
    }

    public void doB() {
        // ...
        if (serviceA != null) {
            serviceA.doA();
        }
    }
}

// During initialization
ServiceBImpl b = new ServiceBImpl();
ServiceAImpl a = new ServiceAImpl(b);
b.setServiceA(a);

Thus, breaking cycles through interfaces, lazy initialization, or intermediaries can eliminate cyclic dependency issues.