Một số vấn đề với enum singletons:
Cam kết thực hiện chiến lược
Thông thường, "singleton" đề cập đến một chiến lược triển khai, không phải là một đặc tả API. Rất hiếm khi Foo1.getInstance()
tuyên bố công khai rằng nó sẽ luôn trả về cùng một ví dụ. Nếu cần, việc triển khai Foo1.getInstance()
có thể phát triển, ví dụ, để trả về một thể hiện cho mỗi luồng.
Với Foo2.INSTANCE
chúng tôi công khai tuyên bố rằng trường hợp này là các ví dụ, và không có cơ hội để thay đổi điều đó. Chiến lược thực hiện có một trường hợp duy nhất được đưa ra và cam kết.
Vấn đề này không làm tê liệt. Ví dụ, Foo2.INSTANCE.doo()
có thể dựa vào một đối tượng trợ giúp cục bộ của luồng, để có một thể hiện trên mỗi luồng một cách hiệu quả .
Mở rộng lớp Enum
Foo2
mở rộng một siêu hạng Enum<Foo2>
. Chúng ta thường muốn tránh các siêu lớp; đặc biệt trong trường hợp này, siêu hạng bị ép buộc Foo2
không liên quan gì đến những gì Foo2
được cho là. Đó là một sự ô nhiễm đối với hệ thống phân cấp loại ứng dụng của chúng tôi. Nếu chúng ta thực sự muốn một siêu hạng, thường thì đó là một lớp ứng dụng, nhưng chúng ta không thể, Foo2
siêu hạng đó đã được sửa.
Foo2
kế thừa một số phương thức ví dụ thú vị như name(), cardinal(), compareTo(Foo2)
, gây nhầm lẫn cho Foo2
người dùng. Foo2
không thể có name()
phương thức riêng ngay cả khi phương thức đó được mong muốn trong Foo2
giao diện.
Foo2
cũng chứa một số phương thức tĩnh vui
public static Foo2[] values() { ... }
public static Foo2 valueOf(String name) { ... }
public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)
mà dường như là vô nghĩa với người dùng. Dù sao thì một singleton thường không nên có các phương thức tĩnh xung (trừ các phương thức getInstance()
)
Tính tuần tự
Nó là rất phổ biến cho các singletons là trạng thái. Những singletons nói chung không nên được tuần tự hóa. Tôi không thể nghĩ ra bất kỳ ví dụ thực tế nào có ý nghĩa khi vận chuyển một singleton trạng thái từ VM này sang VM khác; một singleton có nghĩa là "duy nhất trong VM", không phải "duy nhất trong vũ trụ".
Nếu việc tuần tự hóa thực sự có ý nghĩa đối với một singleton có trạng thái, thì singleton nên xác định rõ ràng và chính xác ý nghĩa của việc khử lưu trữ một singleton trong một VM khác trong đó một singleton cùng loại có thể tồn tại.
Foo2
tự động cam kết chiến lược tuần tự hóa / giải tuần tự đơn giản hóa. Đó chỉ là một tai nạn đang chờ để xảy ra. Nếu chúng ta có một cây dữ liệu tham chiếu một cách khái niệm một biến trạng thái Foo2
trong VM1 tại t1, thông qua việc tuần tự hóa / giải tuần tự hóa, giá trị sẽ trở thành một giá trị khác - giá trị của cùng một biến Foo2
trong VM2 tại t2, tạo ra một lỗi khó phát hiện. Lỗi này sẽ không xảy ra với Foo1
âm thầm không thể chỉnh sửa.
Hạn chế của mã hóa
Có những thứ có thể được thực hiện trong các lớp học bình thường, nhưng bị cấm trong enum
các lớp học. Ví dụ: truy cập một trường tĩnh trong hàm tạo. Lập trình viên phải cẩn thận hơn vì anh ta làm việc trong một lớp học đặc biệt.
Phần kết luận
Bằng cách cõng trên enum, chúng tôi lưu được 2 dòng mã; nhưng giá quá cao, chúng tôi phải mang theo tất cả các hành lý và hạn chế của enum, chúng tôi vô tình thừa hưởng "tính năng" của enum có hậu quả không lường trước được. Ưu điểm duy nhất bị cáo buộc - tính tuần tự tự động - hóa ra là một bất lợi.