2009-12-14 28 views
5

Tôi muốn:ServiceLocator và Mở/Đóng Nguyên tắc

  1. Hãy thường đòi hỏi các dịch vụ có thể nhìn thấy tất cả các lớp học cần đến chúng,
  2. với tối thiểu là soạn sẵn, và
  3. mà không bị mất testability !

Đó là một dự án nhỏ và tôi nghĩ DI có thể quá mức cần thiết, nhưng có thể tôi đã sai? Nhưng dù sao, tôi đã được tập trung vào các ServiceLocator pattern as described by Martin Fowler

Trong một lớp khách hàng xây dựng, tôi có một cái gì đó như thế này:

this->db = Locator::getDb(); 
this->log = Locator::getLogger(); 

Sau đó, phần còn lại của lớp phương pháp truy cập dịch vụ thông qua các thuộc tính những thành viên, ví dụ như :

this->fooModel = new fooModel(this->db); 
fooItem1234 = this->fooModel->findById(1234); 

Tuy nhiên tôi cũng sẽ giống như mức độ tầm nhìn cho "mô hình" đối tượng (như fooModel ở trên) vì chúng được truy cập từ nhiều nơi khác nhau và không có cần thiết phải có nhiều hơn một ví dụ. Vì vậy, suy nghĩ ban đầu của tôi là mở rộng Locator để có một ::getFooModel() nhưng bây giờ có vẻ như tôi đang vi phạm Nguyên tắc Mở/Đóng, vì tôi sẽ phải sửa đổi Locator mỗi khi tôi giới thiệu một lớp mô hình mới.

Để thỏa mãn OCP, tôi có thể sử dụng Trình định vị dịch vụ động (cũng được mô tả trên trang của Fowler), tuy nhiên tôi không hoàn toàn được bán vì lý do tương tự như ông, tức là nó không đủ rõ ràng.

Một giải pháp khác là chỉ làm cho tất cả các phương thức của mô hình của tôi tĩnh. Vì vậy:

fooItem1234 = FooModel::findById(1234); 

Tôi thích điều này vì không có bản mẫu. Tôi chỉ có thể tạo một lớp mô hình mới và bắt đầu gọi nó từ bất kỳ đâu bằng một dòng. Nhưng bây giờ mô hình phụ thuộc vào Locator để tìm kết nối DB của nó và tôi không chắc tôi cảm thấy thế nào về điều đó. Đối với một, nếu tôi đã bao giờ cần phải có hai fooModels mở trên các kết nối cơ sở dữ liệu riêng biệt, nó sẽ là một mớ hỗn độn và/hoặc không thể. Điều đó nói rằng, tôi không thực sự cần phải làm điều đó hiện tại vì vậy tùy chọn này có vẻ hơi hấp dẫn.

Cuối cùng, có DI. Nhưng như tôi đã nói ở trên, tôi nghĩ rằng nó có thể là quá nhiều cho dự án nhỏ này.

Kết luận: Tôi hơi bị kẹt ở đây và sẽ đánh giá cao một số lời khuyên từ các chuyên gia về StackOverflow!

Trả lời

7

Tại sao bạn cho rằng DI quá mức cần thiết cho dự án của bạn? Các mẫu DI chẳng hạn như Constructor Injection là cách đơn giản và sạch hơn Service Locator (mà tôi xem là một mẫu chống).

Tôi coi Service Locator là một mẫu chống đối vì nó hoàn toàn không rõ ràng đối với người dùng API mà phụ thuộc cần phải có; do đó, người ta có thể dễ dàng gọi các phương thức trên các đối tượng của bạn trong một ngữ cảnh mà Trình định vị dịch vụ sẽ ném và API cung cấp cho bạn hoàn toàn không có đầu mối nào cho rằng đây là trường hợp.

Bạn không cần DI Container để sử dụng DI. Nếu chỉ có một dự án đơn giản, bạn có thể sử dụng những gì được gọi là DI Man nghèo nơi bạn kết nối phụ thuộc theo cách thủ công.

+0

Có nghĩa là tôi sử dụng hộp chứa khi tôi nói tôi nghĩ DI sẽ quá mức, xin lỗi. Và cảm ơn câu trả lời! Tôi lấy nó khi bạn nói Constructor Injection bạn đang nói tôi chỉ nên vượt qua các đối tượng dbconn và logger của tôi vào các hàm tạo của các lớp phụ thuộc vào chúng? Nếu vậy, đây thực sự là những gì tôi đang làm. Sau đó, vì lý do nào đó, tôi quyết định phải thêm logger vào prototype của constructor của mỗi class là xấu. Nhưng bây giờ bạn đã làm cho tôi suy nghĩ về nó, nó có vẻ có ý nghĩa hơn nhiều so với những gì tôi đã cố gắng để làm với ServiceLocator này. – oops

+1

Tuyệt. Sau đó, những gì bạn thường kết thúc làm là để ngăn xếp hoặc bọc phụ thuộc. Có thể bạn sẽ có rất nhiều dịch vụ cấp thấp, nhưng bạn thường có thể quấn hai hoặc ba trong số này trong các đối tượng có ý nghĩa, và sau đó chỉ tiêm một trong các dịch vụ này thay vì ba dịch vụ cấp thấp. Bạn có thể lặp lại điều này nhiều lần vì bạn muốn giữ số phụ thuộc giảm cho các lớp riêng lẻ. –

+0

Điều gì về xếp chồng/gói không hoàn toàn liên quan đến những thứ - ví dụ như DBconn và logger từ ví dụ của tôi ở trên - vào một đối tượng gọi là "config" hoặc là hình thức xấu? – oops

3

... và không cần phải có nhiều trường hợp.

Bạn đang trộn táo và cam. Thực tế là bạn chỉ cần một cá thể của một lớp cho một ứng dụng, không phải là điều tương tự vì nó là một ý tưởng tốt để làm cho cá thể đó có sẵn trên toàn cầu. Với DI bạn không thay đổi cardinality - vẫn chỉ là một ví dụ. Những gì bạn thay đổi là phạm vi của các biến địa chỉ cho biết ví dụ. Có một sự khác biệt.

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