2010-07-07 15 views
32

Tôi hiểu các nguyên tắc Mã hóa giao diện - để tách riêng việc triển khai khỏi giao diện và để cho phép triển khai giao diện được hoán đổi vào và ra.Bạn có nên luôn mã hóa cho giao diện trong Java

Tôi có nên mã hóa giao diện cho mọi lớp tôi viết hoặc là quá mức không? Tôi không muốn tăng gấp đôi số lượng tệp nguồn trong một dự án trừ khi nó thực sự đáng giá.

Tôi có thể sử dụng các yếu tố nào để quyết định xem có mã hóa theo giao diện hay không?

+0

Xem câu hỏi này: http://stackoverflow.com/questions/3036749/is -it-the-best-practice-to-extract-an-giao diện-cho-mọi-lớp –

+0

Cảm ơn. Đó là những gì tôi đã được sau khi – Tarski

Trả lời

28

Nói chung, tôi đồng ý với các câu trả lời khác: sử dụng giao diện khi bạn biết hoặc dự đoán thay đổi và/hoặc triển khai khác hoặc đi thử nghiệm.

Nhưng không phải lúc nào cũng dễ dàng biết trước những gì có thể thay đổi trong tương lai, đặc biệt nếu bạn không có kinh nghiệm. Tôi nghĩ rằng giải pháp cho vấn đề đó là tái cấu trúc: giữ cho nó đơn giản (= không có giao diện) miễn là nó không cần thiết. Khi nhu cầu phát sinh chỉ đơn giản là thực hiện tái cấu trúc "Introduce/Extract interface" (được hỗ trợ bởi hầu hết các IDE hợp lý).

Khi bạn thực hiện nó chỉ trích xuất những phương pháp thực sự cần thiết bởi người gọi. Đừng ngại trích xuất nhiều hơn thì một giao diện riêng biệt (nếu không phải tất cả các phương thức trích xuất đều thực sự mạch lạc).

Một trình điều khiển tái cấu trúc có thể là thử nghiệm: nếu bạn không thể dễ dàng kiểm tra điều gì đó với các lớp chỉ xem xét giới thiệu một/một số giao diện. Điều này cũng sẽ cho phép bạn sử dụng chế nhạo có thể đơn giản hóa việc thử nghiệm trong nhiều trường hợp.

Edit: dựa trên nhận xét Tarski của tôi đã nhận ra thêm một quan trọng kịch bản/điều chỉnh các báo cáo theo thời gian:
Nếu bạn cung cấp một API bên ngoài (đối với các dự án [sub] khác, hoặc thực sự giải phóng nó "vào hoang dã ") sau đó sử dụng các giao diện trong API (ngoại trừ các lớp giá trị đơn giản) hầu như luôn là một ý tưởng hay.
Nó sẽ cho phép bạn thay đổi impl nếu bạn thích mà không làm phiền mã máy khách. Bạn sẽ chỉ gặp vấn đề nếu bạn cũng phải thay đổi giao diện. Không phá vỡ tính tương thích sẽ rất phức tạp (nếu không phải là không thể).

+0

câu trả lời tuyệt vời. Tôi đã gặp chính xác điều này - Tôi đã có một lớp được sử dụng bởi nhiều dự án khách hàng và bây giờ cần một giao diện để cung cấp một thực hiện thay thế - tôi có thể sử dụng trọng nhưng nó không phải là sạch sẽ. Vấn đề là sau đó tôi cần phải biên dịch lại tất cả các máy khách hiện có để sử dụng giao diện. Khi bạn đặt nó, tôi không biết tôi cần giao diện khi tôi bắt đầu – Tarski

+1

Bạn đúng với việc biên dịch lại, bạn phải thực hiện nó sau khi tái cấu trúc, nhưng chỉ một lần. Sau khi thực hiện được tách biệt độc đáo, vì vậy bạn có thể tự do thay đổi nó/thêm những cái mới mà không cần biên dịch lại. –

+0

Về chỉnh sửa, bạn có thể muốn đọc về: http://martinfowler.com/bliki/PublishedInterface.html – michaelsnowden

9

Không, mọi lớp không được có giao diện. Đó là quá mức cần thiết bình phương.

Bạn sử dụng giao diện khi bạn cần tóm tắt những gì được thực hiện từ cách thực hiện và bạn chắc chắn rằng việc triển khai có thể thay đổi.

Hãy xem API bộ sưu tập java.util để có ví dụ điển hình. Giao diện Danh sách là một sự trừu tượng tốt đẹp cho ý tưởng chung của một Danh sách, nhưng bạn có thể thấy rằng có nhiều cách để thực hiện nó: ArrayList, LinkedList, v.v.

CẬP NHẬT: Vậy trường hợp bạn thiết kế một bê tông là gì lớp học, quyết định sau khi bạn có khách hàng rằng một giao diện là cần thiết, và sau đó bạn phá vỡ khách hàng của bạn bằng cách thêm một giao diện? Yup, đó là những gì sẽ xảy ra. Làm thế nào bạn có thể biết những gì bạn không biết? Không có phần mềm hoặc phương pháp nào có thể khắc phục điều đó.

Tin tốt cho bạn là việc trích xuất một giao diện từ một lớp cụ thể là việc tái cấu trúc dễ dàng để thực hiện cho cả bạn và khách hàng của bạn. IDE thường xuyên xử lý những điều đó. Bạn và khách hàng của bạn nên tận dụng lợi thế của họ.

Tôi muốn nói rằng các lớp, như dịch vụ và sự kiên trì, phải luôn có giao diện. Bất cứ điều gì có thể được proxied nên có một giao diện. Nếu bạn đang làm Spring AOP, bất cứ điều gì mà bạn muốn trang trí với một khía cạnh nên có một giao diện.

Đối tượng mô hình hoặc giá trị, như Người hoặc Địa chỉ hoặc Điện thoại, không được có giao diện. Một đối tượng giá trị bất biến không nên có giao diện.

Phần còn lại rơi vào các khu vực màu xám. Sử dụng phán đoán tốt nhất của bạn.

+2

Nhưng nếu bạn không biết bạn đang đi để cần sự trừu tượng? VÍ DỤ. Bạn mã một lớp không có giao diện, các máy khách của bạn phụ thuộc vào lớp, sau đó bạn cần thực hiện khác nhưng không thể trích xuất một giao diện mà không phá vỡ khả năng tương thích nhị phân. – Tarski

+0

^mục này. Ngoài ra, thực sự khó có thể tạo ra một giao diện và có một lớp thực hiện nó không? Liệu nó thực sự mất nhiều thời gian hơn để chỉ làm điều đó? – GreenieMeanie

11

tôi sử dụng nó khi có ít nhất một trong các cách sau đây là đúng:

1) Tôi muốn tách các module liên quan/classes lẫn nhau, và tôi muốn nó được phản ánh bởi sự phụ thuộc gói java.

2) Khi tách là rất quan trọng về xây dựng phụ thuộc

3) Khi thực hiện có thể thay đổi thông qua cấu hình hoặc tự động khi chạy (thường là do một số mẫu thiết kế)

4) Khi tôi muốn có một để có thể kiểm tra được, tôi làm cho "các điểm liên kết" của nó thành các giao diện tài nguyên bên ngoài, để tôi có thể sử dụng các triển khai giả lập.

5) Ít phổ biến hơn: Khi tôi muốn có tùy chọn hạn chế quyền truy cập vào một số lớp học. Trong trường hợp này, phương thức của tôi trả về một giao diện thay vì lớp thực tế, vì vậy người gọi biết rằng tôi không mong đợi anh ta thực hiện các phép toán khác trên giá trị trả về.

+0

+1 cho khả năng kiểm tra và giới hạn truy cập –

2

Câu chuyện dài ngắn gọn, không.Bạn là người sáng tạo ứng dụng, vì vậy bạn có ý tưởng phong nha về những gì có thể thay đổi. Một số cuốn sách mẫu thiết kế đi một chút điên trên nó theo ý kiến ​​của tôi vì họ dường như luôn luôn đẩy thiết kế để giao diện và không thực hiện không có vấn đề gì. Đôi khi, nó chỉ là quá mức cần thiết. Đối với ứng dụng mới nhất của tôi (kích thước nhỏ), tôi có một giao diện cơ sở dữ liệu bởi vì tôi nghĩ rằng có một cơ hội sau này tôi có thể chuyển nó vào web và chuyển sang MySQL. Tất nhiên trong thực tế, nó sẽ dễ dàng để tạo ra một giao diện cơ sở dữ liệu xuống đường từ lớp hiện tại của tôi và chỉ cần thêm "thực hiện myDbInterface" sau đó với một vài thay đổi nhỏ. Điều này hoạt động vì tôi là nhà phát triển duy nhất. Trên một nhóm lớn hơn hoặc loại sản phẩm khác, đó có thể là một câu trả lời khác. Chỉ cần sử dụng bản án tốt nhất của bạn (sau khi đọc tất cả các câu trả lời SO tốt của khóa học).

1

Tôi thích nghĩ rằng người dùng sử dụng giao diện khi khả năng cắm và tiềm năng cho hành vi khác nhau là quan trọng. Dịch vụ là hoàn toàn phù hợp. Người ta có thể muốn một thực hiện mặc định, nhưng giả mạo (mocking) vv là khác. Điều này rõ ràng có nghĩa là phải có một intf vì sẽ luôn có ít nhất 2 biểu mẫu.

Các loại giá trị mặt khác phải là lớp cuối cùng. Chúng không bao giờ được kéo dài. Các loại giá trị bao gồm một cái gì đó như Suburb, MimeType. Nếu có các biến thể của thành phần sử dụng này. Như một mục tiêu tôi cố gắng và đặt ít hành vi nếu có trong các loại giá trị của tôi. Việc xác thực loại đơn giản nó kết thúc tốt đẹp ... có lẽ là điều phức tạp nhất mà nó thực hiện. Ví dụ: Một lớp Color lấy r/g/b nên xác nhận rằng mỗi thành phần nằm trong khoảng từ 0 đến 255 và nó là của nó.

0

Có giao diện sử dụng khi bạn mong đợi một hành vi thay đổi. . Trong tương lai.

Hoặc lớp học của bạn có thể xử lý các thay đổi một cách rõ ràng.

ví dụ:

public static void main(String s[]) 
{ 
Employee e1=new Employee(new Salesman()); 
Employee e2=new Employee(new Manager()); 

system.out.println(e1.performaction()); 
system.out.println(e1.performaction()); 
} 

Class Employee 
{ 

//which changes frequently 
Authority a; 

public Employee(Authority a) 
{ 
this.a=a; 
}  
public String performAction() 
{ 
a.action(); 
} 
} 

// ----------------------------------------- -------------------------

interface Authority 
{ 
public String action(); 
} 

class Manager implements Authority 
{ 
public String action() 
{ 
returns "I manages People"; 
} 

class SalesMan implements Authority 
{ 
    public String action() 
{ 
returns "I Sell things Company makes "; 
} 
} 
Các vấn đề liên quan