打破循环依赖以使用依赖注入

Break cyclic dependency in order to use dependency injection

我刚开始使用 dagger 2 and have not used any other dependency injection framework before. Now I'm stuck with a cyclic dependency and I don't know how to solve it properly. Consider the following example in a server application, which uses the Reactor pattern 和 Java NIO:

我有一个 Handler 对象附加到选择键,当新信息到达网络时执行:

class Handler implements Runnable {
  Server server;
  Client client;

  public void run {
    // static factory method that eventually calls a method on server, passing in 'client' as argument
    Command.parse(input).execute(server, client); 

  }

  public void send(String string) {
    // enqueu string and inform reactor about interest in sending
  }
}

Client class 保存有关已连接客户端的一些状态。所有连接的客户端都在 Server class.

中管理
class Client {
  Handler h;

  public send(String response) {
    h.send(response);          
  }
}

当新的输入到达时,处理程序创建Command对象,在服务器上执行它们,服务器最终会响应客户端。

所以我现在正在做的是在 Handler 中手动创建一个 Client 对象,传入 this 引用,以便能够发送响应:

client = new Client(this);

所以我现在的问题是:设计有问题吗?是否可以将 ClientHandler 解耦?或者我应该忍受这个而不使用依赖注入 everywhere?

感谢您的建议

如果您希望客户端能够通过处理程序发回消息,那么以下可以打破您的循环:

// lives in a common package both classes access
public interface ResponseClass {
     public void sendSomeMessage(String message);
}

public class Handler { // handler can also implement ResponseClass directly but I prefer using an additional class for flexibility.
     public void whenYouCreateClient() {
         Client client = new Client(new HandlerWrapper(this)); 
     }

     public static class HandlerWrapper implements ResponseClass {
         private final Handler handler;

         public HandlerWrapper(Handler handler) { this.handler = handler; }

         public void sendSomeMessage(String message) {
             handler.send(message);
         }
     }

     public void send(String string) {
         // enqueu string and inform reactor about interest in sending
     }
}

public class Client {
    ResponseClass rc; // naming should be improved :)

    public void sendMessage(String message) {
        rc.sendSomeMessage(message);
    }
}

现在运行时,您的 类 仍然捆绑在一起,但就您的设计而言,您的客户端仅附加到通用 ResponseClass。

你可以有这样的层次结构:

通用 <-- 客户端 <-- 处理程序

处理程序知道客户端和通用的位置 而客户只知道共同点。 (假设你把接口放在common包里)

而不是 客户端 <--> 处理程序

我特意使用 sendSomeMessage 来强调它是您在 wrapper/interface 上调用的另一种方法,但您当然可以随意命名它们。

一句话:我没有使用 dagger2,所以我不能肯定地说我所做的可以使用那个产品来完成,但这就是我解耦这种循环依赖的方式

我意识到我真正想解决的不是打破ClientHandler之间的依赖关系,而是使用依赖注入而不是new运算符。

我正在寻找的解决方案:将 ClientFactory 注入到 Handler 的构造函数中,然后使用 clientFactory.create(this) 创建一个 Client 对象。出色的库 AutoFactory 允许您使用简单的 @AutoFactory 注释创建这样的工厂。创建的class的构造函数会自动注解为@Inject.