Tại sao nên ưu tiên giao diện cho một lớp Java?


75

PMD sẽ báo cáo vi phạm vì:

ArrayList<Object> list = new ArrayList<Object>();

Vi phạm là "Tránh sử dụng các kiểu triển khai như 'ArrayList'; sử dụng giao diện thay thế".

Dòng sau sẽ sửa lỗi vi phạm:

List<Object> list = new ArrayList<Object>();

Tại sao nên dùng cái sau với Listthay vì ArrayList?


Câu trả lời:


80

Sử dụng giao diện trên các loại cụ thể là chìa khóa để đóng gói tốt và để ghép nối mã của bạn một cách lỏng lẻo.

Bạn cũng nên làm theo phương pháp này khi viết các API của riêng mình. Nếu bạn làm vậy, sau này bạn sẽ thấy rằng việc thêm các bài kiểm tra đơn vị vào mã của bạn (sử dụng kỹ thuật Mocking) sẽ dễ dàng hơn và thay đổi cách triển khai cơ bản nếu cần trong tương lai.

Đây là một bài báo hay về chủ đề này.

Hy vọng nó giúp!


1
Và điều gì về việc sử dụng "Bộ sưu tập" thay vì "Danh sách", vì vậy chúng ta tiến thêm một bước trong trừu tượng ...?
user1156544

31

Điều này được ưu tiên vì bạn tách mã của mình khỏi việc triển khai danh sách. Sử dụng giao diện này cho phép bạn dễ dàng thay đổi việc triển khai, ArrayList trong trường hợp này, thành một triển khai danh sách khác mà không thay đổi bất kỳ phần còn lại nào của mã miễn là nó chỉ sử dụng các phương thức được xác định trong Danh sách.


14

Nói chung, tôi đồng ý rằng việc tách giao diện khỏi việc triển khai là một điều tốt và sẽ giúp mã của bạn dễ bảo trì hơn.

Tuy nhiên, có những ngoại lệ mà bạn phải xem xét. Việc truy cập các đối tượng thông qua các giao diện sẽ thêm một lớp hướng dẫn bổ sung sẽ làm cho mã của bạn chậm hơn.

Để quan tâm, tôi đã chạy thử nghiệm tạo ra mười tỷ lượt truy cập tuần tự vào ArrayList có độ dài 1 triệu. Trên chiếc MacBook 2,4Ghz của tôi, việc truy cập ArrayList thông qua giao diện List mất trung bình 2,10 giây, khi khai báo kiểu ArrayList mất trung bình 1,67 giây.

Nếu bạn đang làm việc với danh sách lớn, nằm sâu bên trong một vòng lặp bên trong hoặc hàm thường được gọi, thì đây là điều cần xem xét.


@Owen: +5 Insightful re: Sự khác biệt về hiệu suất ... Rất bất ngờ
Ande Turner

2
Câu trả lời này tuy nhiên cho thấy các nguyên cần thiết có thể rất nhỏ: stackoverflow.com/questions/890687/...
Raedwald

1
Chà! 0,5 giây cho mười tỷ lượt truy cập, tức là 1 lượt truy cập giao diện chậm hơn một nửa nano giây so với lượt truy cập theo lớp! Tất nhiên đây là lý do để không bao giờ sử dụng giao diện.
Ingo

6

ArrayList và LinkedList là hai triển khai của Danh sách, là một tập hợp các mục có thứ tự. Về mặt logic, không thành vấn đề nếu bạn sử dụng ArrayList hay LinkedList, vì vậy bạn không nên hạn chế kiểu đó.

Điều này trái ngược với nói, Bộ sưu tập và Danh sách, là những thứ khác nhau (Danh sách ngụ ý sắp xếp, Bộ sưu tập thì không).


2

Tại sao cái sau với List nên được sử dụng thay vì ArrayList?

Đó là một thực tiễn tốt: Chương trình để giao diện thay vì triển khai

Bằng cách thay thế ArrayListbằng List, bạn có thể thay đổi cách Listtriển khai trong tương lai như bên dưới tùy thuộc vào trường hợp sử dụng kinh doanh của bạn.

List<Object> list = new  LinkedList<Object>(); 
/* Doubly-linked list implementation of the List and Deque interfaces. 
 Implements all optional list operations, and permits all elements (including null).*/

HOẶC LÀ

List<Object> list = new  CopyOnWriteArrayList<Object>(); 
/* A thread-safe variant of ArrayList in which all mutative operations
 (add, set, and so on) are implemented by making a fresh copy of the underlying array.*/

HOẶC LÀ

List<Object> list = new  Stack<Object>(); 

/* The Stack class represents a last-in-first-out (LIFO) stack of objects.*/

HOẶC LÀ

một số cách Listthực hiện cụ thể khác .

Listgiao diện xác định hợp đồng và thực hiện cụ Listthể có thể được thay đổi. Theo cách này, giao diện và triển khai được kết hợp chặt chẽ với nhau.

Câu hỏi SE liên quan:

"Lập trình với giao diện" có nghĩa là gì?


Và điều gì về việc sử dụng "Bộ sưu tập" thay vì "Danh sách", vì vậy người ta có thể sử dụng Danh sách hoặc Bộ, ví dụ
user1156544

1

Ngay cả đối với các biến cục bộ, việc sử dụng giao diện trên lớp cụ thể cũng có ích. Cuối cùng, bạn có thể gọi một phương thức nằm ngoài giao diện và rất khó để thay đổi việc triển khai Danh sách nếu cần. Ngoài ra, tốt nhất là sử dụng lớp hoặc giao diện ít cụ thể nhất trong một khai báo. Nếu thứ tự phần tử không quan trọng, hãy sử dụng Bộ sưu tập thay vì Danh sách. Điều đó mang lại cho mã của bạn sự linh hoạt tối đa.


1

Các thuộc tính của các lớp / giao diện của bạn nên được hiển thị thông qua các giao diện vì nó cung cấp cho các lớp của bạn một hợp đồng hành vi để sử dụng, bất kể việc triển khai như thế nào.

Tuy nhiên...

Trong khai báo biến cục bộ, không có ý nghĩa gì khi làm điều này:

public void someMethod() {
List theList = new ArrayList();
//do stuff with the list
}

Nếu nó là một biến cục bộ, chỉ cần sử dụng kiểu. Nó vẫn hoàn toàn có thể được đưa lên giao diện thích hợp của nó và các phương thức của bạn hy vọng sẽ chấp nhận các kiểu giao diện cho các đối số của nó, nhưng đối với các biến cục bộ, hoàn toàn hợp lý khi sử dụng kiểu triển khai làm vùng chứa, đề phòng trường hợp bạn cần triển khai- chức năng cụ thể.


1

Nói chung đối với dòng mã của bạn, bạn không cần bận tâm đến các giao diện. Nhưng, nếu chúng ta đang nói về API thì có một lý do thực sự chính đáng. Tôi có lớp nhỏ

class Counter {
    static int sizeOf(List<?> items) {
        return items.size();
    }
}

Trong trường hợp này là yêu cầu sử dụng giao diện. Bởi vì tôi muốn tính kích thước của mọi triển khai có thể bao gồm cả tùy chỉnh của riêng tôi. class MyList extends AbstractList<String>....


Nếu bạn viết mã cho các triển khai như ArrayList, có mọi khả năng bạn có thể sử dụng các phương thức triển khai ngay cả khi bạn có thể làm điều tương tự với các phương thức giao diện. Điều này sẽ ràng buộc mã của bạn với việc triển khai - khiến việc chuyển đổi giữa các triển khai sau này trở nên khó khăn hơn.
Champ

0

Giao diện được hiển thị cho người dùng cuối. Một lớp có thể triển khai nhiều giao diện. Người dùng tiếp xúc với giao diện cụ thể có quyền truy cập vào một số hành vi cụ thể được xác định trong giao diện cụ thể đó.

Một giao diện cũng có nhiều triển khai. Dựa trên hệ thống kịch bản sẽ làm việc với các kịch bản khác nhau (Thực hiện giao diện).

cho tôi biết nếu bạn cần giải thích thêm.


0

Giao diện thường có biểu diễn tốt hơn trong chế độ xem trình gỡ lỗi so với lớp cụ 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.