2013-08-09 37 views
8

Tôi có mã lấy biểu đồ hai chân làm đầu vào và trả về bản đồ có khóa "1" có giá trị là danh sách "nút trong set1" và khóa "2" có giá trị là danh sách "nút trong set2" . Bây giờ, bản đồ có thể thay đổi. Về lý thuyết tôi nên sử dụng một bản sao phòng thủ để trả lại một bản đồ. Nhưng, trong trường hợp này là nó thực sự cần thiết? Nó xuất hiện một overkill.Nên sao chép bản sao phòng thủ?

ví dụ:

class BiPartite { 

    Graph graph; 
    Map bipartite 

    Bipartite(graph) { 
     this.graph = graph; 
    } 

    void calcBipartite() { 
    // calculate map 
    } 

    Map getMap() { 
    // should i make defensive copy ? Appears overkill. 
    } 
} 
+0

Nếu giá trị bạn đang quay trở lại là một thông tin có nguồn gốc được tính toán khi đang bay, không cần phải tạo bản sao phòng thủ. Bạn có tính toán giá trị trả về của getMap mỗi khi phương thức được gọi không? – HariKrishnan

+4

Được cảnh báo rằng người gọi đã có quyền truy cập bên ngoài vào các giá trị bên trong của đối tượng này vì bạn không sao chép 'đồ thị', giả sử' Đồ thị' có thể thay đổi. – jpmc26

Trả lời

6

Nó phụ thuộc :)

  • Bạn có thể ghi lại lớp học của bạn cho phù hợp, xác định rằng bản đồ trở lại là một cái nhìn trực tiếp có thể thay đổi về tình trạng có thể thay đổi của đối tượng song phương. Tôi sẽ không khuyên bạn nên tuy nhiên.
  • Bạn có thể bọc Bản đồ nội bộ bằng Collections.unmodifiableMap(map) trong tài liệu getMap() phản ánh trạng thái có thể thay đổi của đối tượng BiPartite. Đó có thể là một cách tiếp cận hợp lệ miễn là đối tượng BiPartite không được coi là luồng an toàn. Nếu khách hàng muốn giữ Bản đồ trả lại dưới dạng hình chụp nhanh ổn định, cô ấy có thể tự sao chép bản đồ đó. Nếu điều đó là không cần thiết, cô ấy có thể hưởng lợi từ hoạt động gói nhanh.
  • Bạn luôn có thể trả lại bản sao đầy đủ. Điều đó có ý nghĩa nhất nếu bạn thực sự làm cho đối tượng BiPartite trở thành chủ đề an toàn. Trong trường hợp đó, bạn cũng sẽ phải đồng bộ hóa mọi hoạt động của bản đồ nội bộ (bao gồm cả thao tác sao chép bản đồ!).

Về cơ bản nó tóm tắt: Hãy suy nghĩ về cách sử dụng lớp BiPartite và phương pháp của nó, chọn thực hiện phù hợp và ghi rõ hành vi của lớp và lý do đằng sau.

1

Có bạn nên, Bởi vì nếu không thì khách hàng có thể thay đổi lĩnh vực riêng của lớp học của bạn làm cho lớp học của bạn cư xử sai.

1

Tùy thuộc vào quy ước của mã của bạn. Tôi làm theo một quy ước sao chép bất cứ điều gì bạn muốn giữ lại. tức là trách nhiệm của người gọi.

Điều này hiệu quả hơn, nhưng không mạnh mẽ nếu bạn không biết người gọi sẽ tuân theo quy ước này.

5

Có, bạn nên trả lại bản sao phòng thủ. Nếu bạn đang lo lắng về việc sử dụng tài nguyên, bạn có thể trở lại một bản đồ đó là một cái nhìn unmodifiable của đồ riêng tư của bạn:

return Collections.unmodifiableMap(bipartite); 
+0

Vâng, đó là ý của tôi. – Joni

+0

Xin lưu ý rằng 'Collections.unmodifiableMap()' là * không * một bản sao - chỉ một chế độ xem có tất cả các hoạt động ghi bị tắt. Đọc câu trả lời (bản gốc) thật dễ nhầm lẫn cả hai. – creinig

+1

Theo tôi, một cái nhìn bất biến là một lựa chọn tốt hơn so với một bản sao. Điều này để lại những cân nhắc về hiệu suất trong tay người gọi; họ có thể quyết định xem họ có cần chi tiêu và không gian thời gian tạo chi phí bản sao hay không. Nếu không, về cơ bản họ có một bản sao giá rẻ. – jpmc26

2

Từ "LUÔN" hiếm khi thích hợp khi giải thích mô hình và thực hành lập trình tốt. Tất cả phụ thuộc vào ngữ cảnh.

Trong trường hợp của bạn là BiPartite#getMap và chính lớp đó là "gói riêng tư" để khách hàng (người dùng mã của bạn) sẽ không thể sử dụng trực tiếp. Nếu bạn biết rằng bạn không bao giờ lưu trữ hoặc trả lại bản đồ đó bên ngoài ranh giới của gói đó thì nó khá an toàn để nói rằng bạn không cần phải tạo bản sao phòng thủ.

0

Bản sao phòng thủ là một điều tồi tệ bởi vì hầu hết các khung công tác java mà tôi gặp đều mong đợi một getter luôn trả về cùng một giá trị và làm điều đó nhanh chóng.

Nếu bạn muốn lưu từ khách hàng bị lỗi của mã, bạn chỉ nên trưng ra phương thức calcBipartite() và để cho nó trả về một Bản đồ mới được tính toán. Máy khách sử dụng phương thức này phải quyết định cách đối tượng được tạo được sử dụng và bao nhiêu lần calcBipartite() được gọi.

Nếu bạn là khách hàng duy nhất của mã của bạn, bạn không nên sao chép cũng không quấn.

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