2015-01-28 16 views
5

Ho appena iniziato a utilizzare dagger 2 e non ho mai utilizzato alcun altro framework di integrazione delle dipendenze. Ora sono bloccato con una dipendenza ciclica e non so come risolverlo correttamente. Si consideri il seguente esempio in un'applicazione server, che utilizza il Reactor pattern con Java NIO:Dipendenza ciclica di interruzione per utilizzare l'iniezione di dipendenza

Ho un oggetto Handler attaccato ad un tasto di selezione che viene eseguito quando nuove informazioni arriva sulla rete:

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

Il La classe Client mantiene uno stato del client connesso. Tutti i client connessi sono gestiti nella classe Server.

class Client { 
    Handler h; 

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

Quando arrivano nuove ingresso, il gestore crea gli Command oggetti, li esegue sul server, e il server infine risponderà al cliente.

Quindi quello che sto facendo in questo momento, è la creazione di un oggetto Client manualmente Handler, passando un riferimento this, al fine di essere in grado di inviare la risposta:

client = new Client(this); 

Quindi la mia domanda ora è : Qualcosa non va nel design? È possibile disaccoppiare Client e Handler? O dovrei semplicemente vivere con questo e non usare l'iniezione di dipendenza everywhere?

Apprezzo il vostro suggerimenti

risposta

2

mi sono reso conto che quello che Stavo davvero cercando di risolvere non era la rottura della dipendenza tra Client e Handler, ma per utilizzare l'iniezione di dipendenza anziché l'operatore new.

La soluzione che cercavo: Iniettare un ClientFactory al costruttore di Handler e utilizzare clientFactory.create(this) per creare un oggetto Client invece. La brillante libreria AutoFactory consente di creare una tale fabbrica con una semplice annotazione @AutoFactory. Il costruttore della classe creata viene automaticamente annotato con @Inject.

3

Se si desidera che il cliente sia in grado di inviare un messaggio indietro attraverso handler, quindi il seguente può rompere il ciclo:

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

Ora runtime vostre classi sono ancora legati insieme ma per quanto riguarda il design, il tuo cliente è collegato solo a un ResponseClass generico.

si può avere una gerarchia simile:

comune < - cliente < - handler

cui gestore conosce di cliente e comuni e cliente conosce solo di comune. (Supponendo che si mette l'interfaccia nel pacchetto comune)

invece di cliente < -> handler

ho volutamente usato sendSomeMessage evidenziare che si tratta di un metodo diverso di chiamare lui ont involucro/interfaccia, ma naturalmente si può chiamali come preferisci.

Un'osservazione: Non ho usato dagger2 quindi non posso dire per certo che quello che faccio può essere fatto utilizzando quel prodotto, ma questo è come vorrei scindere questo tipo di dipendenza ciclica

+0

Se l'ho ottenuto correttamente, avrei comunque bisogno di costruire l'oggetto Client nel mio oggetto Handler e passare un riferimento a me stesso ('new Client (new HandlerWrapper (this))'). Sono nuovo alla cosa dell'iniezione di dipendenza, ma se ho capito bene, non dovresti mai usare l'operatore 'new'. – S1lentSt0rm

+1

+1 per applicare [Interface_segregation_principle] (http://en.wikipedia.org/wiki/Interface_segregation_principle) anche chiamato [Inversion_of_control] (http://en.wikipedia.org/wiki/Inversion_of_control). – k3b

+0

@ S1lentSt0rm: Al fine di rendere 'Client' e' Handler' non dipendenti dalla DI-Library, tutta la costruzione di servizi e gestori deve essere eseguita in un modulo di cablaggio separato al di fuori del businesslog – k3b

Problemi correlati