2010-05-26 23 views
31

Tôi có một đối tượng lưu trữ một số dữ liệu trong danh sách. Việc triển khai có thể thay đổi sau đó và tôi không muốn hiển thị việc triển khai nội bộ cho người dùng cuối. Tuy nhiên, người dùng phải có khả năng sửa đổi và truy cập bộ sưu tập dữ liệu này. Hiện tại tôi có nội dung như sau:Sử dụng Danh sách hoặc Bộ sưu tập có tốt hơn không?

public List<SomeDataType> getData() { 
    return this.data; 
} 

public void setData(List<SomeDataType> data) { 
    this.data = data; 
} 

Điều này có nghĩa là tôi đã cho phép các chi tiết triển khai nội bộ bị rò rỉ không? Tôi có nên làm việc này thay thế không?

public Collection<SomeDataType> getData() { 
    return this.data; 
} 

public void setData(Collection<SomeDataType> data) { 
    this.data = new ArrayList<SomeDataType>(data); 
} 
+9

Một điều cần lưu ý là nếu bạn trả lại bộ sưu tập hoặc danh sách thực tế như vậy, bạn cho phép người khác làm bất cứ điều gì họ muốn, bao gồm xóa các mục hoặc thậm chí xóa toàn bộ nội dung. Bạn có thể nên trả lại một trình bao bọc không thể thay đổi hoặc bản sao của danh sách. –

+1

@PaulTomblin đúng, nhưng chi phí quá mức và nhân tạo cho hệ thống. Unmodifiable wrappers có ý nghĩa khi làm việc với các đối tượng được quản lý bởi middleware persistency, và thậm chí chỉ trong những trường hợp hiếm hoi. – comeGetSome

+0

@comeGetSome, đó là lý do tại sao tôi nói "có thể" thay vì "phải". Nó sẽ phụ thuộc vào trường hợp sử dụng - nếu tôi đang tạo API cho người khác sử dụng, tôi sẽ trả về một bản sao hoặc một trình bao bọc. Nếu nó là cho bản thân tôi hoặc cho các đồng nghiệp đáng tin cậy, tôi sẽ đặt một "KHÔNG CHỊU ĐIỀU CHỈNH GIÁ TRỊ NÀY" trong javadocs và để nó ở đó. –

Trả lời

24

Nó chỉ phụ thuộc, bạn có muốn người dùng của mình có thể lập chỉ mục vào dữ liệu không? Nếu có, hãy sử dụng Danh sách. Cả hai đều là giao diện, vì vậy bạn không bị rò rỉ chi tiết triển khai, thực sự, bạn chỉ cần quyết định chức năng tối thiểu cần thiết.

0

Tôi có quan tâm đến việc che giấu biểu diễn nội bộ dữ liệu của mình cho người dùng bên ngoài, tôi sẽ sử dụng XML hoặc JSON. Dù bằng cách nào, chúng khá phổ biến.

+0

có nghĩa là kiểu trả về String luôn không? – erdogany

+0

Tất nhiên. XML và JSON có ý định khá phổ biến, và cái gì có thể phổ biến hơn một chuỗi? – Cyberherbalist

+2

Vâng, nếu tôi chuyển dữ liệu giữa các ứng dụng, tôi sẽ sử dụng mã hóa của loại đó. Nhưng nếu tôi đang nói về một giá trị trả về từ một hàm ... chuyển đổi nó thành XML, trả về nó như là một String, và sau đó người gọi phải phân tích cú pháp XML? Đó là rất nhiều phức tạp và trên không chỉ để trả về một mảng. – Jay

1

Có, giải pháp thay thế đầu tiên của bạn sẽ làm chi tiết triển khai bị rò rỉ nếu nó không phải là một phần trong hợp đồng giao diện của bạn mà phương pháp sẽ luôn trả về Danh sách. Ngoài ra, cho phép mã người dùng thay thế bản sao bộ sưu tập của bạn có phần nguy hiểm, bởi vì việc triển khai thực hiện chúng có thể không hoạt động như bạn mong đợi.

Tất nhiên, việc bạn tin tưởng người dùng là bao nhiêu. Nếu bạn lấy triết lý Python rằng "tất cả chúng ta đều là người lớn đồng ý ở đây" thì phương pháp đầu tiên là tốt. Nếu bạn nghĩ rằng thư viện của bạn sẽ được các nhà phát triển thiếu kinh nghiệm sử dụng và bạn cần phải làm tất cả những gì bạn có thể để "giữ trẻ" và đảm bảo họ không làm điều gì sai trái thì tốt hơn là không để họ đặt bộ sưu tập và thậm chí không trả lại bộ sưu tập thực tế. Thay vào đó hãy trả lại một bản sao (nông) của nó.

+1

java.util.Collections chứa các phương thức tĩnh như unmodifiableList() chỉ đơn giản là bọc các bộ sưu tập sao cho tất cả các phương thức có thể sửa đổi các lỗi trả về bộ sưu tập thay thế. Kể từ khi instantiating các wrappers là một hoạt động liên tục thời gian nó là thích hợp hơn ngay cả một bản sao nông (mà mã khách hàng có thể làm cho chính nó nếu nó cần một bộ sưu tập có thể thay đổi.) –

0

Tùy thuộc vào những gì đảm bảo bạn muốn cung cấp cho người dùng. Nếu dữ liệu được tuần tự sao cho thứ tự của các phần tử quan trọng và bạn đang cho phép các bản sao, thì hãy sử dụng một danh sách. Nếu thứ tự của các phần tử không quan trọng và các bản sao có thể hoặc không được phép, thì hãy sử dụng một bộ sưu tập. Vì bạn đang thực sự trả về bộ sưu tập cơ bản, bạn không nên có cả hàm get và set, chỉ có một hàm get, vì bộ sưu tập trả về có thể bị thay đổi. Ngoài ra, việc cung cấp một chức năng thiết lập cho phép loại bộ sưu tập được thay đổi bởi người dùng, trong khi bạn có thể muốn cho loại cụ thể được kiểm soát bởi bạn.

5

Sử dụng loại chung nhất, là Bộ sưu tập, có ý nghĩa nhất trừ khi có một số lý do rõ ràng để sử dụng loại cụ thể hơn - Danh sách. Nhưng bất cứ điều gì bạn làm, nếu đây là một API cho tiêu dùng công khai được rõ ràng trong tài liệu hướng dẫn những gì nó làm; nếu nó trả về một bản sao nông của bộ sưu tập nói như vậy.

7

Khi trả lại triển khai giao diện hoặc lớp có phân cấp cao, quy tắc chung là loại trả về được khai báo phải là mức CAO NHẤT cung cấp chức năng tối thiểu mà bạn sẵn sàng đảm bảo cho người gọi, và người gọi cần một cách hợp lý. Ví dụ, giả sử những gì bạn thực sự trở lại là một ArrayList. ArrayList triển khai Danh sách và Bộ sưu tập (trong số những thứ khác). Nếu bạn mong đợi người gọi cần sử dụng hàm get (int x), thì nó sẽ không hoạt động để trả về một Collection, bạn sẽ cần trả về một List hoặc ArrayList. Miễn là bạn không thấy bất kỳ lý do tại sao bạn sẽ thay đổi việc triển khai của bạn để sử dụng một cái gì đó khác ngoài danh sách - nói một Set - thì câu trả lời đúng là trả về một List. Tôi không chắc chắn nếu có bất kỳ chức năng trong ArrayList mà không có trong danh sách, nhưng nếu có, cùng một lý do sẽ áp dụng. Mặt khác, khi bạn trả lại một Danh sách thay vì một Bộ sưu tập, bạn hiện đã bị khóa trong quá trình triển khai của mình ở một mức độ nào đó. Bạn càng đưa vào API của mình, bạn càng ít hạn chế trong việc cải thiện trong tương lai.

(Trên thực tế, tôi hầu như luôn luôn trả về một List trong những tình huống như vậy, và nó đã không bao giờ đốt cháy tôi. Nhưng tôi có lẽ thực sự phải trả lại một bộ sưu tập.)

9

độc lập về khả năng index vào danh sách thông qua Danh sách .get (int), người dùng (hoặc bạn) có kỳ vọng rằng các yếu tố của bộ sưu tập là một thứ tự đáng tin cậy và có thể dự đoán được không? Bộ sưu tập có thể có bội số của cùng một mục không? Cả hai đều là những kỳ vọng của các danh sách không phổ biến với các bộ sưu tập tổng quát hơn. Đây là những bài kiểm tra tôi sử dụng khi xác định trừu tượng nào để lộ cho người dùng cuối.

14

Trả lại danh sách phù hợp với lập trình cho Giao diện phù hợp cao nhất.

Trả lại bộ sưu tập sẽ gây ra sự mơ hồ cho người dùng vì bộ sưu tập được trả lại có thể là: Đặt, Danh sách hoặc Hàng đợi.

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