2015-01-28 21 views
5

Tôi chỉ mới bắt đầu sử dụng dagger 2 và chưa sử dụng bất kỳ khung tiêm phụ thuộc nào khác trước đây. Bây giờ tôi bị mắc kẹt với sự phụ thuộc theo chu kỳ và tôi không biết cách giải quyết nó đúng cách. Hãy xem xét ví dụ sau đây trong một ứng dụng máy chủ, trong đó sử dụng các Reactor pattern với Java NIO:Phá vỡ sự phụ thuộc chu kỳ để sử dụng tiêm phụ thuộc

Tôi có một đối tượng Handler gắn liền với một phím chọn được thực hiện khi thông tin mới đến trên mạng:

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

Các Client lớp chứa một số trạng thái về ứng dụng được kết nối. Tất cả các Khách hàng được kết nối được quản lý trong lớp học Server.

class Client { 
    Handler h; 

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

Khi đầu vào mới đến, Trình xử lý tạo các đối tượng Command, thực thi chúng trên máy chủ và máy chủ cuối cùng sẽ trả lời ứng dụng.

Vì vậy, những gì tôi đang làm ngay bây giờ, đang tạo ra một đối tượng Client bằng tay trong Handler, đi qua trong một tài liệu tham khảo this, để có thể gửi câu trả lời:

client = new Client(this); 

Vì vậy, câu hỏi của tôi bây giờ là : Có vấn đề gì với thiết kế không? Có thể tách riêng ClientHandler không? Hoặc tôi chỉ nên sống với điều này và không sử dụng tiêm phụ thuộc everywhere?

Tôi đánh giá cao đề xuất của bạn

Trả lời

2

tôi nhận ra rằng những gì Tôi thực sự đã cố gắng để giải quyết không phá vỡ sự phụ thuộc giữa ClientHandler, nhưng để sử dụng tiêm phụ thuộc thay vì nhà điều hành new.

Giải pháp mà tôi đang tìm kiếm: Tiêm một số ClientFactory vào hàm tạo Handler và sử dụng clientFactory.create(this) để tạo đối tượng Client thay thế. Thư viện rực rỡ AutoFactory cho phép bạn tạo một nhà máy như vậy với chú thích đơn giản @AutoFactory. Hàm tạo của lớp được tạo sẽ tự động được chú thích với @Inject.

3

Nếu bạn muốn các khách hàng để có thể gửi tin nhắn trở lại thông qua xử lý, thì sau đây có thể phá vỡ chu kỳ của bạn:

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

Bây giờ Runtime lớp học của bạn vẫn gắn cùng nhau nhưng theo như thiết kế của bạn thì khách hàng của bạn chỉ được gắn với một ResponseClass chung.

bạn có thể có một hệ thống phân cấp như:

chung < - client < - handler

nơi handler biết của khách hàng và phổ biến và client chỉ cần biết của chung. (Giả sử bạn đặt giao diện trong gói chung)

thay vì client < -> handler

Tôi cố tình sử dụng sendSomeMessage để nhấn mạnh rằng đó là một phương pháp khác nhau mà bạn gọi ont ông bao bọc/giao diện nhưng ofcourse bạn có thể đặt tên cho chúng theo cách bạn muốn.

Một nhận xét: Tôi không sử dụng dagger2 vì vậy tôi không thể nói chắc chắn rằng những gì tôi làm có thể được thực hiện sử dụng sản phẩm đó, nhưng đây là cách tôi sẽ tách loại này phụ thuộc cyclic

+0

Nếu tôi nhận được chính xác, tôi vẫn sẽ cần phải xây dựng đối tượng Client trong đối tượng Handler của tôi và chuyển một tham chiếu tới chính tôi ('new Client (new HandlerWrapper (this))'). Tôi mới vào điều tiêm phụ thuộc, nhưng nếu tôi hiểu nó đúng, bạn không bao giờ nên sử dụng toán tử 'new'. – S1lentSt0rm

+1

+1 để áp dụng [Interface_segregation_principle] (http://en.wikipedia.org/wiki/Interface_segregation_principle) cũng được gọi là [Inversion_of_control] (http://en.wikipedia.org/wiki/Inversion_of_control). – k3b

+0

@ S1lentSt0rm: Để làm cho 'Client' và' Handler' không phụ thuộc vào DI-Library, tất cả các dịch vụ và trình xử lý phải được thực hiện trong một modul dây riêng biệt bên ngoài businesslogic – k3b

Các vấn đề liên quan