2015-01-28 10 views
5

Właśnie zacząłem używać dagger 2 i wcześniej nie stosowałem żadnej innej struktury wtrysku zależności. Teraz utknąłem w cyklicznej zależności i nie wiem, jak rozwiązać to poprawnie. Rozważmy następujący przykład w aplikacji serwera, który wykorzystuje Reactor pattern z Java NIO:Przerwij cykliczną zależność, aby użyć wstrzyknięcia zależności.

Mam Handler obiekt dołączony do klawisza wyboru, który jest wykonywany, gdy nowe informacje przybywa w sieci:

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 
    } 
} 

The Client klasa przechowuje pewien stan o podłączonym kliencie. Wszyscy podłączeni klienci są zarządzani w klasie Server.

class Client { 
    Handler h; 

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

Kiedy przybywa nowy wejściowego, Handler tworzy Command obiektów, wykonuje je na serwerze, a serwer ostatecznie odpowie na kliencie.

Więc co robię teraz, jest stworzenie Client obiekt ręcznie w Handler, przechodzącą w this odniesienia, aby móc wysłać odpowiedź:

client = new Client(this); 

Więc moje pytanie jest teraz : Czy coś jest nie tak z projektem? Czy można odłączyć Client i Handler? Czy powinienem po prostu żyć z tym i nie używać iniekcji zależności everywhere?

Doceniam wasze sugestie

Odpowiedz

2

zdałem sobie sprawę, że to, co Naprawdę starałem się rozwiązać, nie łamiąc zależności między Client i Handler, ale używać iniekcji zależności zamiast operatora new.

Rozwiązanie szukałem: wstrzykiwać do ClientFactory do konstruktora Handler i używać clientFactory.create(this) stworzyć Client obiekt zamiast. Świetna biblioteka AutoFactory umożliwia utworzenie takiej fabryki za pomocą prostej adnotacji @AutoFactory. Konstruktor utworzonej klasy jest automatycznie opatrzony komentarzem pod numerem @Inject.

3

Jeśli chcesz klient będzie mógł wysłać wiadomość z powrotem przez przewodnika, wówczas następujące mogą złamać cyklu:

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

Teraz Runtime twoje zajęcia są nadal przywiązane razem, ale jeśli chodzi o twój projekt, twój klient jest podłączony tylko do ogólnej klasy ResponseClass.

można mieć hierarchię jak:

wspólnego < - Klient < - handler

gdzie zna obsługi klienta i wspólnym i klient wie tylko powszechne. (Zakładając, że można umieścić interfejs we wspólnym opakowaniu)

zamiast klienta < -> handler

ja celowo wykorzystywane sendSomeMessage podkreślić, że jest to inna metoda zadzwonić ont on wrapper/interfejsu, ale oczywiście można nazwij je, jak chcesz.

Jedna uwaga: nie używać dagger2 więc nie mogę powiedzieć na pewno, że to co robię może być wykonane przy użyciu tego produktu, ale to jest jak bym oddzielenie tego rodzaju cyklicznej zależności

+0

Jeśli mam go poprawnie, nadal będę musiał skonstruować obiekt klienta w moim obiekcie Handler i przekazać w odniesieniu do mnie ('new Client (new HandlerWrapper (this))'). Jestem nowicjuszem w dziedzinie wtrysku zależności, ale jeśli dobrze to zrozumiałem, nigdy nie powinieneś używać operatora 'new'. – S1lentSt0rm

+1

+1 za zastosowanie [Interface_segregation_principle] (http://en.wikipedia.org/wiki/Interface_segregation_principle) zwanego również [Inversion_of_control] (http://en.wikipedia.org/wiki/Inversion_of_control). – k3b

+0

@ S1lentSt0rm: Aby "Klient" i "Handler" nie były zależne od biblioteki DI, cała konstrukcja usług i modułów obsługi powinna być wykonana w jednym oddzielnym module połączeń poza domeną businesslogic – k3b

Powiązane problemy