2010-04-17 74 views
18

Tôi đã lập trình Java trong một vài khóa học tại Đại học và tôi có câu hỏi sau:Phương thức giao diện Java Phương pháp: Mỗi lớp có thực hiện một giao diện không?

Có phương pháp nào được chấp nhận rằng mọi lớp nên triển khai giao diện? Nó được coi là thực hành xấu không làm như vậy? Bạn có thể mô tả một tình huống mà nó không phải là một ý tưởng tốt để sử dụng giao diện?

Edit: Cá nhân, tôi thích các khái niệm của việc sử dụng giao diện cho tất cả mọi thứ như một phương pháp và thói quen, thậm chí nếu nó không phải là rõ ràng có lợi. Eclipse tự động tạo một tệp lớp với tất cả các phương thức, do đó, nó không lãng phí bất kỳ lúc nào.

+0

liên quan: https://www.symphonious.net/2011/06/18/the-single-implementation-fallacy/ – jaco0646

+0

liên quan: https://marekdec.wordpress.com/2011/12/06/clear-interface-per-class-antipattern/ – jaco0646

+0

Liên quan: http://martinfowler.com/bliki/InterfaceImplementationPair.html – jaco0646

Trả lời

21

Bạn không cần tạo giao diện nếu bạn không sử dụng nó.

Thông thường bạn cần một giao diện khi:

  • chương trình của bạn sẽ cung cấp một số triển khai cho thành phần của bạn. Ví dụ, một thực hiện mặc định là một phần của mã của bạn, và một thực hiện mô hình được sử dụng trong một bài kiểm tra JUnit. Một số công cụ tự động tạo việc triển khai mô hình, ví dụ như EasyMock.
  • Bạn muốn sử dụng tiêm phụ thuộc cho lớp này, với khung làm việc như Spring hoặc JBoss Micro-Container. Trong trường hợp này, bạn nên chỉ định các phụ thuộc từ một lớp với các lớp khác bằng cách sử dụng một giao diện.
+4

+1 để kiểm tra đơn vị và chế nhạo. Tôi sử dụng giao diện trên hầu như tất cả các lớp học của tôi một cách chính xác vì lý do này. –

+4

@Philippe Mocking khuôn khổ hiện đại có thể mô phỏng các lớp học. –

+0

xin lỗi câu hỏi ngu ngốc, nhưng khung mocking là gì? –

17

Tiếp theo nguyên tắc YAGNI một lớp học nên thực hiện một giao diện nếu bạn thực sự cần nó. Nếu không, bạn sẽ đạt được gì từ nó?

Chỉnh sửa: Giao diện cung cấp một loại trừu tượng. Chúng đặc biệt hữu ích nếu bạn muốn trao đổi giữa các triển khai khác nhau (nhiều lớp thực hiện cùng một giao diện). Nếu nó chỉ là một lớp duy nhất, thì không có được.

2

Giao diện là cách để có được một đa hình. Vì vậy, nếu bạn chỉ có một triển khai thực hiện, một lớp đặc biệt là loại, Bạn không cần một giao diện.

+1

Giao diện cung cấp trừu tượng, không đóng gói. –

+0

Tôi đã suy nghĩ về tính đa hình. Tôi không lý do tại sao tôi nói đóng gói. Lỗi của tôi. Lỗi chính tả. –

+0

Trong khi tôi là người đề xuất giao diện, đa hình có thể đạt được trong Java mà không cần sử dụng giao diện vì bạn có thể mở rộng bất kỳ lớp không phải cuối cùng nào và quá tải bất kỳ phương thức phi tĩnh cuối cùng nào – Kirby

5

Không, không cần thiết cho mọi lớp để triển khai giao diện. Chỉ sử dụng các giao diện nếu chúng làm cho mã của bạn sạch hơn và dễ viết hơn.

Nếu chương trình của bạn không có nhu cầu hiện tại cho có nhiều hơn 1 thực hiện cho một lớp nhất định, sau đó bạn không cần một giao diện. Ví dụ, trong một chương trình cờ vua đơn giản tôi đã viết, tôi chỉ cần 1 loại đối tượng Hội đồng quản trị. Một bàn cờ là một bàn cờ là một bàn cờ. Làm cho một giao diện Board và thực hiện mà sẽ chỉ cần thêm mã để viết và duy trì.

Nó rất dễ dàng để chuyển sang một giao diện nếu bạn cuối cùng cần nó.

+1

nếu bạn tạo lập trình đơn giản. mã của bạn đã được nhiều dự án sử dụng: sau đó bạn sẽ được coi là một nhà thiết kế tồi vì bạn sẽ phá vỡ mã của khách hàng. – user310291

+1

Vâng vâng - có một số trường hợp giao diện có ý nghĩa và các lớp trong các thư viện phân tán là một trong những trường hợp đó. Nhưng OP không hỏi về trường hợp cụ thể đó, anh ta hỏi về tất cả các lớp. –

0

Khi tôi thiết kế một hệ thống mới từ đầu tôi sử dụng một cách tiếp cận theo định hướng thành phần, mỗi thành phần (10 hoặc nhiều lớp) cung cấp một giao diện, điều này cho phép tôi (đôi khi) sử dụng lại chúng.

  • Khi thiết kế một công cụ (Hoặc một hệ thống đơn giản) Tôi nghĩ đây không nhất thiết phải là một khuôn khổ mở rộng, tôi giới thiệu các giao diện khi cần thực hiện lần hai.

  • tôi thấy một số sản phẩm mà tiếp xúc với hầu hết các chức năng của một giao diện, phải mất đơn giản là quá nhiều thời gian để hiểu được sự phức tạp không cần thiết.

1

Cách tốt để học những gì được coi là phương pháp tốt, đặc biệt là khi nói đến thiết kế cấu trúc mã, là xem xét mã sẵn có tự do. Với Java, ví dụ rõ ràng là hãy xem JDK system libraries.

Bạn sẽ tìm thấy nhiều ví dụ về các lớp không triển khai bất kỳ giao diện nào hoặc có nghĩa là được sử dụng trực tiếp, chẳng hạn như java.util.StringTokenizer.

+2

Tôi muốn thêm thông báo trước rằng ngôn ngữ Java và các thực hành lập trình có thể đã phát triển kể từ khi lớp được viết ban đầu và mã không thay đổi để phá vỡ khả năng tương thích ngược.Ví dụ, một số thư viện hệ thống vẫn sử dụng 'static final' int hoặc String hằng số cho những thứ tốt hơn bằng cách sử dụng enums, các lớp lấy hoặc trả về các đối tượng yêu cầu một phép diễn tốt hơn bằng cách sử dụng Generics, và các lớp mà phương thức của nó chỉ lấy Vectors hoặc Hashtables vì API Bộ sưu tập chưa được viết. – Nate

3

Tôi thấy rằng có ích khi xác định phương thức công khai của lớp trong giao diện tương ứng và khi xác định tham chiếu đến các lớp khác sử dụng nghiêm ngặt tham chiếu giao diện. Điều này cho phép dễ dàng đảo ngược kiểm soát, và nó cũng tạo điều kiện cho thử nghiệm đơn vị với chế nhạo và stubbing. Nó cũng cung cấp cho bạn sự tự do thay thế việc thực hiện với một số lớp khác thực hiện giao diện đó, vì vậy nếu bạn sử dụng TDD, điều đó có thể làm cho mọi thứ dễ dàng hơn (hoặc nhiều hơn nếu bạn là người chỉ trích TDD)

1

Nếu bạn sử dụng Dịch vụ Mẫu Giao diện nhà cung cấp trong giao diện ứng dụng của bạn khó mở rộng hơn các lớp trừu tượng. Nếu bạn thêm phương thức vào giao diện, tất cả các nhà cung cấp dịch vụ phải được viết lại. Nhưng nếu bạn thêm phương thức không trừu tượng vào lớp trừu tượng, thì không ai trong số các nhà cung cấp dịch vụ phải được viết lại.

Giao diện cũng làm cho việc lập trình trở nên khó khăn hơn nếu chỉ một phần nhỏ của các phương thức giao diện thường có ý nghĩa thực hiện đầy đủ.

+0

Đây không phải là vấn đề với giao diện mỗi lần - chúng chỉ đơn giản là thiết kế phân cấp kém. Bạn sẽ có cùng một vấn đề nếu bạn sử dụng cùng một hệ thống phân cấp được thiết kế xấu bằng cách mở rộng các lớp. – Nate

4

Tạo giao diện cho mọi lớp là không cần thiết. Một số lý do thường được trích dẫn bao gồm chế nhạo (không cần thiết với khung mocking hiện đại như Mockito) và cho việc tiêm phụ thuộc (ví dụ: Mùa xuân, cũng không cần thiết trong việc triển khai hiện đại).

Tạo giao diện nếu bạn cần, đặc biệt là để chính thức tạo tài liệu giao diện công khai. Có một vài trường hợp cạnh tiện lợi (ví dụ: giao diện điểm đánh dấu).

Đối với những gì đáng giá, trong một dự án gần đây, chúng tôi sử dụng giao diện cho mọi thứ (cả DI và chế nhạo được coi là lý do) và hóa ra là một sự lãng phí hoàn toàn và thêm nhiều phức tạp. thêm một giao diện khi thực sự cần thiết để mô phỏng một cái gì đó trong trường hợp hiếm hoi nó là cần thiết. Cuối cùng, tôi chắc chắn rằng một người nào đó sẽ gió lên và xóa tất cả các giao diện không liên quan vào cuối tuần.

Tôi lưu ý rằng các lập trình viên C trước tiên chuyển sang Java có xu hướng thích nhiều giao diện ("giống như tiêu đề"). Phiên bản hiện tại của Eclipse hỗ trợ điều này, bằng cách cho phép điều hướng nhấp chuột điều khiển để tạo cửa sổ bật lên yêu cầu giao diện hoặc triển khai.

8

Mọi lớp học thực hiện giao diện (nghĩa là hợp đồng) trong phạm vi vì nó cung cấp API không riêng tư. Cho dù bạn nên chọn để đại diện cho giao diện riêng biệt như một giao diện Java phụ thuộc vào việc thực hiện là "một khái niệm thay đổi".

Nếu bạn hoàn toàn chắc chắn rằng chỉ có một triển khai hợp lý thì không cần giao diện. Nếu không, một giao diện sẽ cho phép bạn thay đổi việc triển khai mà không thay đổi mã máy khách.

Một số người sẽ hét lên "YAGNI", giả sử rằng bạn có toàn quyền kiểm soát việc thay đổi mã nếu bạn phát hiện ra yêu cầu mới sau này. Những người khác sẽ rất sợ rằng họ sẽ cần phải thay đổi API không thể thay đổi - được xuất bản.

Nếu bạn không triển khai giao diện (và sử dụng một số loại nhà máy để tạo đối tượng) thì một số loại thay đổi nhất định sẽ buộc bạn phải phá vỡ Nguyên tắc đóng. Trong một số trường hợp, điều này có thể được chấp nhận về mặt thương mại, ở những trường hợp khác thì không.

Bạn có thể mô tả tình huống sử dụng giao diện không tốt không?

Trong một số ngôn ngữ (ví dụ: C++, C#, nhưng không phải Java), bạn có thể nhận được lợi ích hiệu suất nếu lớp của bạn không chứa phương pháp ảo.

Trong các chương trình nhỏ hoặc ứng dụng không có API được xuất bản, bạn có thể thấy chi phí nhỏ để duy trì các giao diện riêng biệt.

Nếu bạn thấy sự gia tăng đáng kể về độ phức tạp do cách ly giao diện và triển khai thì có thể bạn không sử dụng giao diện làm hợp đồng. Giao diện làm giảm độ phức tạp. Từ quan điểm của người tiêu dùng, các thành phần trở thành các mặt hàng đáp ứng các điều khoản của hợp đồng thay vì các thực thể có các chi tiết triển khai phức tạp theo cách riêng của họ.

+1

"Mọi lớp học đều thực hiện giao diện (nghĩa là hợp đồng) trong phạm vi vì nó cung cấp API không riêng tư". Đó là một quan sát khôn ngoan! –

+0

Liên quan: http://martinfowler.com/bliki/ImplicitInterfaceImplementation.html – jaco0646

-5

Sử dụng Giao diện sắp làm cho khung ứng dụng của bạn linh hoạt để thay đổi. Kể từ khi tôi đã đề cập ở đây (Multiple Inheritance Debates II: according to Stroustrup) nhiều thừa kế đã bị hủy bỏ trong java và C# mà tôi rất tiếc, một trong những nên luôn luôn sử dụng giao diện bởi vì bạn không bao giờ biết những gì tương lai sẽ được.

+7

Chuẩn bị cho tương lai trước khi bạn biết những gì tương lai nắm giữ dẫn đến mã phức tạp không cần thiết. –

2

Để trả lời câu hỏi của OP theo cách rất thẳng thắn: không, không phải tất cả các lớp đều cần triển khai giao diện. Giống như tất cả các câu hỏi về thiết kế, điều này làm giảm sự phán xét tốt nhất của một người. Dưới đây là một vài quy tắc của ngón tay cái tôi thường làm theo:

đối tượng
  • thuần túy chức năng có thể không cần phải (ví dụ mẫu, CharMatcher - mặc dù sau không thực hiện Predicate, nó chỉ là thứ yếu để cốt lõi của nó chức năng)
  • nắm giữ dữ liệu tinh khiết có lẽ không cần đến (ví dụ LogRecord, Locale)
  • Nếu bạn thể hình dung một thực hiện khác nhau của một chức năng nhất định (chẳng hạn, trong -memory Cache so với Cache trên đĩa), hãy thử cách ly chức năng này thành giao diện. Nhưng đừng đi quá xa để dự đoán tương lai.
  • Vì mục đích thử nghiệm, nó là rất thuận tiện khi các lớp học làm I/O hoặc chủ đề bắt đầu dễ dàng giả lập, vì vậy mà người dùng không phải trả tiền phạt khi chạy thử nghiệm của họ.
  • Không có gì là tệ hơn giao diện rò rỉ triển khai cơ bản của nó. Chú ý nơi bạn vẽ đường kẻ và đảm bảo Javadoc của giao diện là trung lập theo cách đó. Nếu không, bạn có thể không cần giao diện.
  • chung nói, nó là một lợi thế cho lớp dành cho tiêu thụ công bên ngoài gói/dự án của bạn để thực hiện các giao diện để dùng của bạn đang ít đi đôi với việc thực hiện bạn du jour.

Lưu ý rằng bạn có thể tìm thấy các ví dụ phản đối cho từng dấu đầu dòng trong danh sách đó. Giao diện rất mạnh, vì vậy chúng cần phải được sử dụng và tạo cẩn thận, đặc biệt nếu bạn đang cung cấp các API bên ngoài (xem this video để thuyết phục chính mình). Nếu bạn quá nhanh trong việc đặt giao diện trước mặt mọi thứ, có thể bạn sẽ kết thúc việc rò rỉ triển khai đơn lẻ của mình và bạn chỉ đang làm mọi thứ phức tạp hơn cho những người theo dõi bạn. Nếu bạn không sử dụng chúng đủ, bạn có thể kết thúc với một codebase cũng khó bảo trì vì mọi thứ đều bị ràng buộc tĩnh và rất khó thay đổi. Danh sách không đầy đủ ở trên là nơi tôi cố gắng vẽ đường kẻ.

0

Giao diện giống như một hợp đồng giữa nhà cung cấp dịch vụ (máy chủ) và người dùng dịch vụ (máy khách) như vậy.

  • Nếu chúng ta đang phát triển một Webservice và chúng tôi đang phơi bày các tuyến đường còn lại qua lớp điều khiển, lớp điều khiển có thể thực hiện các giao diện và những giao diện hoạt động như thỏa thuận giữa dịch vụ web và các ứng dụng khác mà sử dụng dịch vụ web này .
  • giao diện Java như Serializable, Clonnabletừ xa sử dụng để chỉ một cái gì đó để trình biên dịch hoặc JVM.When JVM thấy một lớp mà thực hiện các giao diện này, nó thực hiện một số hoạt động trên để hỗ trợ serialization, sao chép hoặc Gọi phương thức từ xa. Nếu lớp của bạn cần các tính năng này, thì bạn sẽ phải triển khai các giao diện này.

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