2011-01-26 21 views
5

nền nhanhLàm thế nào để trang trí một đối tượng trong Java

Tôi có một hai danh sách (lớn) POJO được thông qua vào một phương pháp trong đó tôi cần phải đảm bảo tính độc đáo trên hai danh sách. Giải pháp tốt nhất tôi có thể thấy là xây dựng hai bộ và kiểm tra xem giao lộ của chúng có trống không.

Vấn đề

Đối với bối cảnh của phương pháp này, và phương pháp này một mình, tôi cần phải ghi đè lên equalshashcode phương pháp của POJO trong câu hỏi.

Những gì tôi đang tìm kiếm

Điều này có vẻ giống như một candiate thủ để trang trí các đối tượng hiện có. Tôi đã xem xét Guava's ForwardingObject nhưng nó có vẻ phù hợp nhất để ủy quyền các đối tượng thực hiện một giao diện nhất định mà không phải là trường hợp của tôi. Nói chung, tôi đang tìm một giải pháp ...

  1. Tránh đối phó tất cả các trường trong POJO lớn (các nhà xây dựng sao chép).
  2. Dễ hiểu và duy trì
  3. tránh tạo ra một lớp học hoàn toàn mới mà kéo dài POJO vì lợi ích của một phương pháp này
+0

Bạn có nói rằng các POJO hiện không thực hiện equals và hashcode rồi và bạn không thể thay đổi chúng để làm như vậy? –

+0

Mẫu trang trí thực sự không có ý nghĩa quá nhiều nếu không có giao diện chung. Mở rộng lớp học là "yuck". –

+0

@Eric: Không, tôi nói rằng POJO bằng và hashcode không có ý nghĩa đối với phương pháp này. Odd có lẽ nhưng đây không phải là lần đầu tiên tôi muốn xác định một bối cảnh bình đẳng. –

Trả lời

3

Tôi chỉ cần đi với lớp trình bao bọc.

Tạo một lớp mới được khởi tạo với POJO của bạn trong hàm tạo. Nó không sao chép POJO, chỉ giữ lại tham chiếu đến bản gốc. Sau đó viết bằng và hashcode tuy nhiên bạn thích trong lớp wrapper đó.

Something như thế này:

public class MySpecialWrapper{ 
    private final BigPojo delegate; 

    public MySpecialWrapper(BigPojo pojo){ 
    this.delegate = pojo; 
    } 

    public int hashCode(){ 
    //insert special impl here. 
    } 

    public boolean equals(Object o){ 
    //insert special impl here. 
    } 
} 

Đặt trường hợp của lớp wrapper vào Sets của bạn và sử dụng để xác minh tính độc đáo. Thêm một phương thức accessor (getDelegate) nếu bạn cần truy cập vào POJO vi phạm trong trường hợp thất bại.

+1

Trông khá giống với câu trả lời của Eric, xin vui lòng xem bình luận của tôi ở đó. –

+1

Tôi không biết bất cứ điều gì ngoài đó sẽ làm điều này cho bạn. Tuy nhiên, như bạn có thể thấy, điều này là khá nhỏ. Đặt một bình luận tốt đẹp ở đầu để làm rõ điều này là gì, và bạn nên vàng. Tôi tôn trọng nhiệm vụ tái sử dụng nội dung đã được xác định. Nhưng, đối với một cái gì đó như thế này, bạn phải cân nhắc rằng so với thời gian dành cho việc tìm kiếm câu trả lời. – rfeak

0

Bạn có thể sử dụng một proxy động để quấn mỗi phần tử:

class VeryBigPOJO {} 

interface PojoWrapper { 
    VeryBigPOJO getPojo(); 
} 

class MyHandler implements InvocationHandler { 
    private VeryBigPOJO ob; 

    public MyHandler(VeryBigPOJO ob) { 
     this.ob = ob; 
    } 

    public Object invoke(Object proxy, Method method, Object[] args) 
      throws Throwable { 
     if(method.getName().equals("getPojo")) 
      return ob; 
     if(method.getName().equals("equals")) 
      //calculate equals 
     if(method.getName().equals("hashCode")) 
      //calculate hashCode 
    } 
} 

Sau đó quấn đối tượng của bạn vào các proxy động:

VeryBigPOJO pojo = ...; 
PojoWrapper wrapper = Proxy.newProxyInstance(MyHandler.class.getClassLoader(), new Class[] { PojoWrapper.class}, new MyWrapper(pojo)) 

Và bây giờ bạn có thể thêm các đối tượng wrapper vào số HashSet.

Tuy nhiên, sẽ không dễ dàng hơn khi xây dựng một đối tượng id nhỏ hơn, không thay đổi ra khỏi pojo lớn? Nó chắc chắn sẽ dễ đọc hơn.

2

Một giải pháp đơn giản là tạo lớp bao bọc cho mỗi lớp POJO. Trình bao bọc giữ một tham chiếu đến cá thể POJO và định nghĩa các phương thức equals và hashcode để tính các giá trị của chúng dựa trên các trường thích hợp trong POJO. Sau đó, bạn có thể sử dụng các lớp Collections bình thường.

+0

Tôi bắt đầu nghĩ theo cùng một cách. Điều này có thể tầm thường, nhưng có lớp bao bọc được xác định trước không? Tôi thích sử dụng lại những gì đã có sẵn để dễ hiểu và đầy đủ. –

+0

+1 Giống như tôi đã nói, bạn thậm chí không cần phải bọc nó, bạn có thể tính toán trước giá trị 'hashCode()' và một định danh sẽ được so sánh trong 'equals()'. – biziclop

+0

@Andrew: Quả thật, đối với trường hợp của bạn, trình bao bọc là giải pháp đơn giản nhất. Bạn không tạo đại biểu. Như @biziclop đã nói, bạn có thể tính giá trị bạn cần ngay trong hàm tạo. Và bạn không nhất thiết phải bao gồm tất cả các thuộc tính trong các phép tính của bạn, chỉ bất cứ điều gì là duy nhất đối với đối tượng. Vì vậy, các wrapper không phải rất phức tạp. Bạn có thể đi xa hơn nữa và thực hiện giao diện Comparable và sử dụng trình bao bọc để sắp xếp, nếu nó hữu ích. Hãy chắc chắn làm theo lời khuyên trong Mục 7 và 8 trong Java hiệu quả ... –

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