2011-08-13 38 views
5

Tôi đang cố gắng để có được tốt hơn với IoC, DI và OOD cho khả năng kiểm tra tốt hơn và khớp nối lỏng lẻo hơn.OOD sử dụng các thùng chứa IoC - cách xây dựng các đối tượng phụ thuộc?

Vì vậy, khi chúng tôi thiết kế các lớp học với việc sử dụng nặng nề của IoC và DI chúng ta có thể endup với các lớp học với nhiều phụ thuộc ví dụ

class Processor 
{ 
    private IService1 m_Service1; 
    private IService2 m_Service2; 
    private IService3 m_Service3; 

    //approach 1 
    public Processor(IService1 service1, IService2 service2, IService3 service3) 
    { 
     m_Service1 = service1; 
     m_Service2 = service2; 
     m_Service3 = service3; 
    } 
    //approach 2 
    public Processor(IContainer container) 
    { 
     m_Service1 = container.Resolve<IService1>(); 
     m_Service2 = container.Resolve<IService2>(); 
     m_Service3 = container.Resolve<IService3>(); 
    } 

    //approach 3 
    public delegate Processor Factory(); 

} 

Im suy nghĩ những gì cần phải là phương pháp thông thường ở đây. Chúng ta có thể rời khỏi nhà xây dựng với 3 thông số, nhưng nếu chúng ta đang xây dựng ứng dụng sử dụng autofac (ví dụ) rất có thể nó sẽ hiếm khi được sử dụng khác hơn bằng cách giải quyết các loại từ một số ví dụ container như

Processor proc = new Processor(
container.Resolve<IService1>(), 
container.Resolve<IService2>(), 
container.Resolve<IService3>()); 

vì vậy tôi nghĩ có lẽ cách tiếp cận 2 là tốt hơn, khi chúng ta phụ thuộc vào nhiều loại từ container. Dù sao, chúng tôi sẽ phải thêm tham chiếu đến autofac ở đâu đó, vì vậy bất kỳ lý do nào để không làm điều đó ngay bây giờ?

Autofac cũng cung cấp nhà máy đại biểu phương pháp tiếp cận

http://code.google.com/p/autofac/wiki/DelegateFactories

var processorFactory = container.Resolve<Processor.Factory>(); 
Processor processor = processorFactory.Invoke(); 

Vì vậy, chúng tôi cũng đã tiếp cận 3 - chúng tôi sẽ không sử dụng nhà thầu để tạo trường lớp của chúng tôi, thay vào đó chúng tôi sẽ gọi đại biểu giải quyết từ thùng chứa và nó sẽ giải quyết sự phụ thuộc cho chúng ta.

Vì im khá mới đối với IoC, khó có thể nói khi nào chúng tôi nên sử dụng 1,2,3. Họ có lợi thế và bất lợi.

Tôi nghĩ rằng nếu lớp học có 1 phụ thuộc, chúng tôi có thể luôn luôn sử dụng cách tiếp cận 1 .. khác hơn là tôi thực sự không chắc chắn nên chọn gì và khi nào.

CẬP NHẬT tôi đã đọc về dịch vụ định vị chống mẫu nhưng Ive đưa ra 4 (hoặc cách tiếp cận thứ 3 true)

thân thiết với ServiceLocator trừ của nó không, chúng tôi vượt qua một đối tượng mà trông như thế này

public class ServiceLocatorObject 
{ 
     private IService1 m_Service1; 
     private IService2 m_Service2; 
     private IService3 m_Service3; 
     public IService1 Service1 {get {return m_Service1;}} 
     public IService2 Service2 {get {return m_Service2;}} 
     public IService3 Service3 {get {return m_Service3;}} 

     public ServiceLocatorObject(IService1 service1, IService2 service2, IService3 service3) 
     { 
      m_Service1 = service1; 
      m_Service2 = service2; 
      m_Service3 = service3; 
     } 
} 

Và bây giờ chúng ta tạo ra

//approach 4 
public Processor(ServiceLocatorObject servicesToUse) 
{ 
    m_Services = servicesToUse; 
} 

Bây giờ chúng tôi đã tách lớp của chúng tôi từ việc triển khai dịch vụ một d của nó rõ ràng những gì phụ thuộc thực sự cần thiết (nếu chúng ta giả định tất cả các dịch vụ availabe trên đối tượng được thông qua được yêu cầu) bởi vì chúng tôi không đi qua một container có thể chứa 100 triển khai. Và đối tượng đó thậm chí có thể được sử dụng lại nếu sự kết hợp dịch vụ 3 đó có thể được yêu cầu trong một số lớp khác trong ứng dụng của chúng tôi. Vì vậy, chúng tôi đang sử dụng hàm tạo DI không phải mẫu ServiceLocator. giao diện rõ ràng và không quá tải với các phụ thuộc, lớp mới có thể là một ứng cử viên tái sử dụng tốt.

Bạn sẽ nói gì về điều này?

Trả lời

6

Mẫu vị trí dịch vụ thường được coi là chống mẫu trong những ngày này (sử dụng vùng chứa.Resolve và injecting the container).Sau khi MUCH đấu tranh với khái niệm này bản thân mình và cố gắng để quyết định nếu tôi thích nó hay ghét nó, tôi đã đến nhận thức cá nhân rằng tôi đồng ý vị trí dịch vụ là một mô hình chống - vì nó làm xáo trộn sự phụ thuộc lẫn nhau tồn tại và đó là một khái niệm cốt lõi của OOP.

Have a đọc ở đây: http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx

Tôi thực sự thích thực tế rằng trong phương án 1, Process RÕ RÀNG thể hiện sự phụ thuộc của nó đối với mỗi người trong số các dịch vụ nó liệt kê là các thông số trong constructor. Nó làm cho các phụ thuộc rất rõ ràng .... và hơn nữa tôi nghĩ nó giúp thúc đẩy thiết kế tốt.

Chỉ cần nói Bộ xử lý mất một IContainer không cho chúng tôi biết rất nhiều ... và do đó bạn cần phải xem xét kỹ hơn để xác định các phụ thuộc lẫn nhau.

+0

liên kết rất hay, cuốn sách đó trông giống như những gì tôi cần. Bạn nghĩ gì về cách tiếp cận thứ 3? –

+0

+1 Xem câu trả lời của tôi để có thêm ý kiến. –

+1

Tôi sử dụng phương pháp tiếp cận thứ ba trên mã của mình ... khi tôi cần phải tiêm một phương tiện để tạo nhiều phiên bản của một loại theo thời gian. Tôi sử dụng Windsor ... vì vậy tôi sử dụng các nhà máy đại biểu rất nhiều, và tiêm Func khi tôi biết xử lý của tôi sẽ cần phải tạo ra nhiều IService1 theo thời gian ... – Jeff

0

Đây không phải về số lượng phụ thuộc, cũng như quyết định của mỗi lớp học. Cách tiếp cận 2 giới thiệu một sự phụ thuộc mới, nhưng nếu bạn muốn dựa vào một container IoC, hơn là một cách tiếp cận tốt. Phương pháp tiếp cận 3 giống như thứ hai, nhưng chúng ta hãy làm một số công cụ trong Nhà máy trong tương lai. Phương pháp tiếp cận 1 là đơn giản nhất, không dựa vào bất cứ điều gì và nên được sử dụng cho các phụ thuộc mà bạn sẽ không thường quản lý thông qua container IoC.

+0

Đây không phải là về số lượng phụ thuộc, cũng không phải một quyết định mỗi lớp. - bạn có thể xây dựng được không? Vì vậy, chúng ta nên chọn cách tiếp cận duy nhất cho toàn bộ ứng dụng và sử dụng nó ở khắp mọi nơi hoặc bạn đang nói gì? Tôi không chắc chắn tại sao nó không thể là một quyết định cho mỗi lớp .. –

+0

Sự lựa chọn để sử dụng container IoC ảnh hưởng đến toàn bộ ứng dụng - mỗi mô-đun phải phụ thuộc vào nó. Phương pháp tiếp cận 1 là tự nhiên - tất cả các nhà phát triển đều hiểu nó. Phương pháp 2 là container cụ thể. Điều tồi tệ nhất bạn có thể làm là trộn chúng lại. Người đọc mã sẽ phải kiểm tra thẩm định nào được sử dụng khi nào, cùng lưu giữ cho người viết bài kiểm tra. –

6

Câu trả lời được đưa ra bởi JeffN825 là đúng, nhưng tôi muốn thêm vào đó mà bạn không bao giờ tạo ra một trường hợp xử lý mới sử dụng một container như thế này:

Processor proc = new Processor(
    container.Resolve<IService1>(), 
    container.Resolve<IService2>(), 
    container.Resolve<IService3>()); 

Thay vào đó, bạn muốn chúng ta hãy container auto-wire sự phụ thuộc và resolve it one go:

Processor proc = container.Resolve<Processor>(); 
+0

cảm ơn, Mark. Bạn có thể nói điều gì đó về cách tiếp cận thứ 3 không? Những tình huống nào tốt hơn so với bộ xử lý được đề xuất của bạn proc = container.Resolve (); hoặc cách tiếp cận thứ nhất? –

+1

Cách tiếp cận thứ ba chỉ là một Nhà máy Tóm tắt trong ngụy trang: http://blog.ploeh.dk/2009/05/28/DelegatesAreAnonymousInterfaces.aspx Nó không thực sự liên quan đến hai cách tiếp cận khác. Bạn sẽ làm gì với nó? –

+0

Xin chào, tôi đã thêm cập nhật cho câu hỏi sau khi đọc một số bài đăng của bạn, bạn nghĩ gì về nó? –

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