2012-11-01 34 views
6

Tôi đã viết một enum Java trong đó các giá trị có các thuộc tính khác nhau. Những thuộc tính này có thể được lưu trữ trong bất kỳ trong các cách sau:Java enums - lựa chọn giữa các trường, phương thức trừu tượng và sơ đồ cấp lớp

Sử dụng các lĩnh vực:

enum Eenum { 
    V1(p1), 
    V2(p2); 

    private final A attr; 

    public A attr() { return attr; } 

    private Eenum(A attr) { 
    this.attr = attr; 
    } 
} 

Sử dụng phương pháp trừu tượng:

enum Eenum { 
    V1 { 
    public A attr() { return p1; } 
    }, 

    V2 { 
    public A attr() { return p2; } 
    } 

    public abstract A attr(); 
} 

Sử dụng bản đồ trình độ lớp:

enum Eenum { 
    V1, 
    V2; 

    public A attr() { return attrs.get(this); } 

    private static final Map<A> attrs; 

    static { 
    ImmutableMap.Builder<Eenum, A> builder = ImmutableMap.builder(); 
    builder.put(V1, p1); 
    builder.put(V2, p2); 
    attrs = builder.build(); 
    } 
} 

Tôi nên quyết định khi nào nên chọn cái nào?

Cảm ơn!

+0

Tôi nghĩ trước tiên bạn nên giải thích cách họ liên hệ ('Eenum' và' A'). –

+0

@BheshGurung, chúng chỉ là một số tên được chọn ngẫu nhiên. 'A' là một kiểu ngẫu nhiên. Nếu chúng có liên quan theo một cách nào đó, tôi sẽ tuyên bố rõ ràng như vậy. – missingfaktor

+0

Tôi tự hỏi ai đã bỏ phiếu để đóng và tại sao. – missingfaktor

Trả lời

0

(tôi trả lời câu hỏi của riêng tôi để tôi có thể chia sẻ một số điều tôi học được khi cố gắng ra mọi thứ.)

Dưới đây là những câu hỏi bạn nên yêu cầu đưa ra quyết định cho trường hợp cụ thể của bạn:

1: Các giá trị thuộc tính có liên quan đến tham chiếu chuyển tiếp không?

Đôi khi thuộc tính của V1 có thể cần tham chiếu đến V2 và ngược lại. Đây không phải là trường hợp hiếm hoi.Nếu bạn đang xử lý như vậy enum, cách tiếp cận 1 chỉ đơn giản là sẽ không hoạt động. Trình biên dịch sẽ (đúng) khiếu nại về các tham chiếu chuyển tiếp bất hợp pháp. Bất kỳ phương pháp nào khác có thể được sử dụng.

Bây giờ, nếu giá trị thuộc tính đắt tiền để tính toán và hằng số, bạn muốn nó chỉ được tính một lần. Với cách tiếp cận 2, bạn phải giới thiệu các biến cục bộ cho mỗi giá trị enum và các kết quả cache ở đó. Điều này là tiết nhưng sẽ cung cấp cho bạn hiệu suất tốt hơn. Với phương pháp tiếp cận 3, kết quả sẽ chỉ được tính một lần và do đó không phải thực hiện thêm bất kỳ công việc nào. Điều này là dễ đọc hơn nhưng phần nào kém hiệu quả hơn so với cách tiếp cận 2. Thiết kế giữa những điều này theo các lệnh giao dịch cụ thể được bảo hành trong trường hợp của bạn.

2: Tôi có cần lưu vào bộ nhớ cache kết quả không?

Tham khảo đoạn thứ hai của dấu đầu dòng trước đó.

Nếu không có tham chiếu chuyển tiếp, bạn cũng có thể sử dụng phương pháp 1. Nhưng nếu tính toán liên quan đến việc tính toán các thuộc tính là phức tạp, bạn nên sử dụng một trong hai cách tiếp cận khác.

3: Các thuộc tính có liên quan đến tất cả các giá trị enum không?

Nếu không, sau đó khá hợp lý, bạn nên sử dụng Map tại đây. Đó là, cách tiếp cận 3.

4: Có bất kỳ giá trị mặc định nào cho một số thuộc tính cho một số giá trị enum không?

Nếu có, bạn có thể sử dụng cả ba phương pháp tiếp cận và tất cả đều cung cấp các bộ cân bằng khác nhau.

Với phương pháp 1: Bạn sẽ xác định hàm tạo phụ trợ để khởi tạo thuộc tính thành giá trị mặc định. Nếu có nhiều thuộc tính như vậy, đây có thể không phải là cách tiếp cận khả thi.

Với cách tiếp cận 2: Điều này thực sự sẽ giống như cách tiếp cận "thứ tư" của Peter Lawrey được đề xuất ở trên. Bạn sẽ có phương thức trả về giá trị mặc định trong phần chính của enum. Và một số giá trị enum sẽ ghi đè phương thức này để trả về một giá trị khác. Đây là, một lần nữa, khá tiết.

Với phương pháp 3: Chỉ kém hiệu quả. Tốt theo mọi cách khác.

3

Tôi sẽ làm điều bạn nghĩ là đơn giản nhất.

Nói chung tôi không viết mã có thể được triển khai bằng dữ liệu. Tôi sẽ sử dụng cái đầu tiên.

trường hợp sử dụng thực tế của tôi có một số thuộc tính mà không liên quan cho tất cả các giá trị enum

Bạn có thể sử dụng kết hợp các phương pháp tiếp cận nếu nó làm cho cảm giác trên cơ sở mỗi thuộc tính.

Tùy chọn thứ tư là không có phương pháp trừu tượng.

enum Eenum { 
    V1 { 
    public A attr() { return p1; } 
    }, 

    V2 { 
    public A attr() { return p2; } 
    }, 
    V3, V4, V5, V6; 

    public A attr() { return defaultA; } 
} 
+0

Đồng ý. Đối với tôi giải pháp đầu tiên đơn giản và rõ ràng nhất – darrengorman

+0

Trường hợp sử dụng thực tế của tôi có một số thuộc tính không liên quan đến tất cả các giá trị enum. Bản đồ có thích hợp hơn trong trường hợp đó không? – missingfaktor

+0

Trường hợp sử dụng thực tế của tôi có một số ràng buộc hơn khiến cả ba phương pháp tiếp cận nhiều hơn hoặc ít hơn cùng độ dài. – missingfaktor

0

Không có trong số đó. Làm điều này:

interface HasAttr<T> { 
    T attr(); 
} 

enum Eenum implements HasAttr<A> { 

    // use "fields" version - ideally with constructor version 

    public A attr() { 
     return field; 
    } 

} 

mô hình này theo mẫu Abstract Type thiết kế cơ bản, cho phép phương pháp như:

public void someMethod(HasAttr<A> hasAttr); // pass anything that is HasAttr<a> 

trong ưu tiên cho loại cố định:

public void someMethod(Eenum eenum); // locked into passing an Eenum 

Ngoài ra, và quan trọng , nó dễ dàng hơn để thử nghiệm để thử nghiệm, đặc biệt là nếu enum của bạn sử dụng các kết nối thực sự, vv

Tôi cấp cho bạn, tất cả điều này chỉ áp dụng nếu enum là "nontrivial". Nếu nó chỉ là một enum cũ đồng bằng, tôi đồng ý nó chỉ là mã sưng lên (mà tôi cũng ghét cay ghét đắng)

+0

Kéo ra một giao diện cho mọi trường (tôi có nhiều trường trong mã thực của tôi) có vẻ vô nghĩa. – missingfaktor

+1

Đặc biệt vì nó sẽ không thêm bất kỳ giá trị nào, đối với trường hợp tôi đang xử lý. – missingfaktor

+0

@Bohemian muốn thêm giải thích về lý do tại sao điều đó tốt hơn? – darrengorman

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