Cách thực hiện chỉ là một phần của giao diện


13

Khi phát triển trong OOP, đôi khi một giao diện / hợp đồng được cung cấp bởi một thư viện mà bạn không thể thay đổi. Hãy gọi giao diện này là J.

Bây giờ bạn có một đối tượng của lớp A tiêu thụ các đối tượng thực hiện giao diện này. Bên trong Chỉ cần một phần nhỏ các định nghĩa của giao diện. Một số lớp đối tượng được tôi tạo ra trong dự án (hãy gọi một trong số chúng là loại D), do đó, có một chi phí trong việc thực hiện mọi thứ bên trong giao diện J.

Tôi muốn triển khai một tập hợp con của chức năng trong giao diện J, nhưng các giải pháp của tôi cho đến nay không làm tôi hài lòng:

  • triển khai mọi khía cạnh của J và sau đó ném "notImcellenceedExceptions" gây hiểu lầm cho người dùng đối tượng của tôi: có vẻ như các đối tượng loại D của tôi tuân thủ giao diện J, nhưng họ không - và những người tiêu dùng khác của đối tượng của tôi (chấp nhận giao diện J) không thể dựa vào tính toàn vẹn của các đối tượng của tôi.
  • Việc triển khai một giao diện mới được xác định cấm tôi sử dụng các đối tượng chỉ thực hiện giao diện J, mặc dù giao diện J hoàn toàn tương thích với giao diện của riêng tôi.
  • Để các đối tượng tùy chỉnh của tôi triển khai giao diện J sẽ tạo ra chi phí đáng kể, vì chúng không cần tất cả chức năng này.

Khi tôi có thể thay đổi giao diện J, tôi sẽ tạo một "siêu giao diện" K có tập hợp con chức năng này của giao diện J và tạo giao diện J kế thừa từ giao diện K. Nhưng tôi không thể thay đổi giao diện J.

Một giải pháp hướng đối tượng cho vấn đề này là gì? Là giải pháp tốt nhất vẫn đang thực hiện giao diện "chỉ" J? Hoặc có những cách OOP để "siêu lớp" một giao diện mà không thay đổi nó?


1
Xem cách các lớp * Adaptor trong Swing làm điều này.

Câu trả lời:


8

nếu bạn không điều khiển giao diện J, bạn sẽ bị kẹt.

bạn có thể, để rõ ràng, triển khai subJ giao diện J của riêng bạn và sử dụng subJ trong mã của riêng bạn để làm rõ rằng các phương thức bổ sung trong giao diện J là không bắt buộc, nhưng tôi không nghĩ rằng nó thực sự mang lại cho bạn nhiều

nếu có thể, hãy thực hiện toàn bộ giao diện J

nếu có thể, hãy liên hệ với chủ sở hữu giao diện J và yêu cầu anh ấy / cô ấy thay đổi nó để phù hợp hơn với mục đích của bạn


2
Như một sự thỏa hiệp: Bạn có thể yêu cầu chủ sở hữu giao diện J kế thừa mẫu SubJ giao diện nhỏ hơn của bạn.
k3b

26

Toàn bộ quan điểm của việc thực hiện một giao diện là cung cấp một hợp đồng chắc chắn giữa người gọi và callee không bao giờ thay đổi trong khi các chi tiết triển khai có thể khác nhau.

Bằng cách thực hiện giao diện J, bạn đang nói với thế giới bên ngoài những gì bạn có thể làm.

Nếu bạn không cần một nửa những gì J làm thì giao diện sẽ thực sự được chia nhỏ vì nó không nhỏ như nó có thể, hoặc bạn phải sử dụng NotImplementedExceptioncác phương thức và thuộc tính bạn không cần. Tuy nhiên, đây không phải là giải pháp tốt nhất vì nó làm giảm sự mong đợi của mọi người về những gì mã của bạn có thể làm.


4

Nếu lớp người tiêu dùng A của bạn không yêu cầu tất cả giao diện J, thì tôi khuyên bạn nên tạo một giao diện mới (gọi là K), mô tả toàn diện tất cả những gì nó yêu cầu.

Điều này cung cấp một tín hiệu rõ ràng cho bất cứ ai sử dụng lớp A về phía hợp đồng của họ là gì. Qua đó cải thiện cơ hội tái sử dụng. Nếu ai đó cần cung cấp một đối tượng thực hiện một giao diện lớn và phức tạp, để làm một việc tương đối đơn giản, họ có thể sẽ tự mình viết bất cứ thứ gì mà lớp A tự làm.

Để cho phép lớp A tiêu thụ các đối tượng thực hiện giao diện J một mình, bạn có thể cung cấp một lớp bao bọc thực hiện giao diện K và chuyển bất kỳ cuộc gọi thích hợp nào cho thành viên J giao diện.


3

Mặc dù tôi đồng ý với các câu trả lời hiện có nói rằng bạn thực sự cần phải thực hiện J hoàn toàn (ngoại trừ các phương thức không được thực hiện) hoặc hoàn toàn không, một cách giải quyết có thể là như sau:

  • Tạo một giao diện K nhỏ hơn là tập con của J và thực hiện các phương thức cần thiết.
  • Tạo một trình bao bọc cho A chấp nhận các đối tượng triển khai J và K.
  • Trong trường hợp thông qua trong J, chỉ cần đẩy nó qua trường hợp của A.
  • Trong trường hợp được thông qua trong K, khởi tạo một triển khai ẩn danh của J, chỉ nối các phương thức từ K đến J ở đó. Truyền kết quả cho trường hợp của A.

Xin lưu ý rằng đây là một giải pháp khá xấu xí, vì nó yêu cầu một trình bao bọc chấp nhận nhiều thứ về cơ bản là cùng một thứ. Nhưng nó đạt được những điều sau đây:

  • Không có thay đổi đối với J hoặc A.
  • Không có triển khai "phơi bày" nào của J không đầy đủ.

Nếu ngôn ngữ OO của bạn không cho phép khởi tạo giao diện ẩn danh, bạn có thể tạo một triển khai giả của giao diện và khởi tạo giao diện đó.


1

Mất bao lâu để thực hiện toàn bộ giao diện?

Nếu bạn mất một khoảng thời gian đáng kể thì điều này cho thấy vấn đề thiết kế và tôi sẽ khuyên bạn (như Steven A. đã làm trước tôi) liên hệ với chủ sở hữu và xem liệu nó có thể được thay đổi trong tương lai không.

Bạn có sử dụng giao diện trong mã của riêng bạn, độc lập với thư viện của giao diện không?

Như Steven A. đã đề xuất, bạn có thể sử dụng giao diện của riêng mình như bạn muốn thấy nó trong mã của riêng bạn. Điều này ít nhất giữ cho mã số kênh của bạn sạch sẽ. Bạn cũng có thể gửi cái này cho chủ sở hữu như giao diện mà bạn mong muốn tìm thấy. Có lẽ anh ấy đồng ý với bạn, hoặc có lẽ anh ấy có thể giải thích cho bạn tại sao giao diện không nên bị chia tách.

Việc triển khai của bạn có bao giờ cần các thành viên không sử dụng giao diện không?

Trong trường hợp bạn có thể mong đợi chúng không bao giờ được gọi vì chúng 'không được hỗ trợ', tôi thích sử dụng NotSupportedException. Điều này đưa ra một dấu hiệu rõ ràng bạn sẽ không bao giờ hỗ trợ giao diện này, thay vì bạn không thực hiện nó.


Ý tưởng tốt về việc sử dụng NotSupportedExceptionnó cho thấy rõ rằng bạn không hỗ trợ phương pháp đó.
ChrisF

@ChrisF: Tôi chỉ sử dụng NotImplementedExceptioncho mã sản xuất, ở đó tôi sẽ viết "TODO: Thực hiện điều này" Đáng buồn thay, họ không bật lên trong danh sách nhiệm vụ của Visual Studio . Nhưng trong thực tế, tôi hầu như không để một phương pháp nào không được thực hiện trong thời gian dài hơn hai ngày. Resharper cũng cho thấy những ngoại lệ in đậm (ít nhất là với thiết lập của tôi). :)
Steven Jeuris

0

Thực hiện những gì bạn cần và ném ngoại lệ NoIm HiệnedException cho những người khác.

Đây là một vấn đề sử dụng. Nếu bạn không sử dụng giao diện hoặc bạn biết mã của mình sẽ không sử dụng giao diện, thì đừng đầu tư thời gian vào việc này, vì bạn không cần đầu tư thời gian vào mã dự phòng.

Làm việc cho nhiệm vụ trong tầm tay và giữ dấu vết tốt để người khác theo dõi nếu họ muốn sử dụng giao diện.

Rất nhiều giao diện trong Java không được triển khai đầy đủ.

Đây là ứng dụng của Apache cho mọi thứ: http://commons.apache.org/lang/api-2.4/org/apache/commons/lang/NotImcellenceedException.html


Có lẽ tranh luận lý do tại sao bạn tin rằng đây là một giải pháp thích hợp. Điều này không thêm gì vào câu hỏi.
Steven Jeuris

không cần phải thực hiện mọi thứ, vì không có nhu cầu thực sự để giải thích mọi thứ. nếu đó là trường hợp của anh ta, các phần của giao diện là dư thừa, anh ta sẽ chọn nó ngay lập tức.
Tên hiển thị
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.