2010-06-23 28 views
20

Mục 3 của Josh Block Hiệu quả Java (Thực thi thuộc tính Singleton với một hàm tạo riêng hoặc một điều tra viên) đề cập rằng "Trong khi phương pháp này vẫn chưa được áp dụng rộng rãi, một kiểu enum phần tử đơn là cách tốt nhất để thực hiện singleton. "Singleton đơn lẻ có phải là một ý tưởng hay không?

Ví dụ:

public enum Elvis { 
     INSTANCE; 
     private final String[] favoriteSongs = 
      { "Hound Dog", "Heartbreak Hotel" }; 
     public void printFavorites() { 
      System.out.println(Arrays.toString(favoriteSongs)); 
     } 
    } 

Tiếp: "Cách tiếp cận này có chức năng tương đương với phương pháp tiếp cận lĩnh vực công cộng, ngoại trừ việc nó ngắn gọn hơn, cung cấp máy móc thiết bị serialization miễn phí, và cung cấp một đảm bảo bọc thép chống lại nhiều instantiation, ngay cả khi đối mặt với các cuộc tấn công xê-ri hóa hoặc phản chiếu tinh vi. "

Điều tiêu cực nhất mà tôi thấy là: không phải là enums không có trạng thái có thể thay đổi được? Nó có vẻ phổ biến để sử dụng một Singleton với nhà nước.

Vì vậy, mẫu này thực sự trở nên phổ biến hơn kể từ ngày xuất bản (ấn bản thứ 2 được xuất bản năm 2008)?

+0

Tôi có phải là người duy nhất không thoải mái về cách thức enums trong Java có thể hoạt động giống như các lớp học không? Có vẻ như Java đã quyết định loại bỏ "các kiểu tìm kiếm tự nhiên" mà bạn có thể làm trong C++ bằng các phương thức nạp chồng, và biến các enum đơn giản thành đốm màu kỳ lạ này. – Uri

+1

C++ tiếp cận enums như một phần mở rộng của việc sử dụng các int để chuyển đổi, vì vậy chúng là các cấu trúc rất đơn giản. Trong Java, mặt khác, enums được hình thành như các lớp hợp pháp, với tất cả các chức năng mà mang lại với nó, chỉ khác nhau trong một của họ (chính) hạn chế về instantiation. Họ có cùng tên bởi vì tập quán của họ chồng lên nhau trong một số lĩnh vực quan trọng, nhưng hãy thận trọng khi so sánh chúng quá chặt chẽ - chúng là những con thú rất khác nhau. – tlayton

+1

@Uri, 'enum's trong Java không chỉ đơn thuần là hành xử giống như các lớp, chúng còn là các lớp _are_. Tất cả chúng đều mở rộng 'java.lang.Enum'. – Pops

Trả lời

10

Trong khi enums thường không được cho là trạng thái có thể thay đổi, thực tế này dựa trên giả định về cách sử dụng enum. Trong khi những giả định này thường giữ, chúng không phải luôn luôn, và một trong những trường hợp như vậy mà chúng không có trong việc tạo ra Singleton.

Mặc dù đây không phải là cách sử dụng phổ biến nhất của enums, nhưng bạn có thể muốn chỉ ra thực tế này trong mã của bạn để bất kỳ lập trình viên nào khác có thể xem nó bị lẫn lộn.

Đối với sự phổ biến của mẫu thiết kế này, tôi đã nhìn thấy nó khá thường xuyên, nhưng không quá nhiều mà tôi muốn nói nó đã trở thành "phổ biến".

3

Enums có thể có trạng thái có thể thay đổi. Nó thường không phải là một ý tưởng tốt bởi vì bản chất của enum là có chính xác các phiên bản X của Type Y trong đó X lớn hơn 1, vì vậy việc tung hứng xung quanh trạng thái (ngoài việc sử dụng các trường/thuộc tính) sẽ trở thành một cơn ác mộng. cần tính đến tất cả trạng thái có thể có của tất cả các hằng số enum X.

Nhưng nếu bạn định xác định enum chỉ với một hằng số; bạn có thể chỉ cần xử lý một hằng số đơn lẻ như một đối tượng bình thường và làm cho tất cả các giả định đi kèm với nó. IOW: vấn đề về việc có phiên bản X của trạng thái biến mất vì X bây giờ là 1.

8

(câu trả lời này giả định rằng một "thi hành" singleton là thực sự những gì bạn muốn, như trái ngược với một de facto singleton bởi khuôn khổ DI bạn quản lý (ví dụ @Singleton của Guice), mà có lẽ là thường xuyên hơn ý tưởng đúng.)

Để phân tách câu hỏi của bạn thành hai: Có thực sự được áp dụng rộng rãi không? Không, không phải là rộng rãi như nó phải được. Nó là một ý tưởng tốt? Vâng!

Một enum Java là một lớp mà chỉ có thể có một bộ N cố định, được mã hóa cứng trong nguồn.

Singleton là một lớp chỉ có thể có một bộ N cố định, được mã hóa cứng trong nguồn. Và N == 1.

Nó đơn giản như vậy!

1

Không enum s không được giả định là có trạng thái có thể thay đổi. Thống kê thường không thể thay đổi được. Singletons chỉ là cách để làm xáo trộn các statics có thể thay đổi được.(Các đối tượng không quốc tịch thực hiện giao diện là một vấn đề khác.)

-3

Đó không phải là một ý tưởng hay.

Nó buộc lớp học của bạn phải kế thừa từ lớp bê tông Enum. Điều đó gây ô nhiễm phân cấp loại của bạn.

Loại INSTANCE phải chính xác Elvis; nó không thể là một số kiểu con của Elvis.

Thông thường, bạn không có quyền tự do lựa chọn cách thể hiện được thể hiện.

Và cú pháp-khôn ngoan, điều này thực sự là quá nhiều đánh máy?

public class Elvis { 
    static public Elvis INSTANCE = new Elvis(); 
+4

Nếu bạn cho rằng từ xa tương đương với những gì bạn đã nhập ở đây, tôi khuyên bạn nên đọc bài viết EJ. Và không ai buộc bạn phải vạch trần Elvis như một Elvis. Bạn có thể phơi bày nó (thông qua một phương thức) như bất kỳ siêu kiểu nào bạn muốn, và đây là một thực hành chung tốt vì nó khiến bạn linh hoạt khi sử dụng khởi tạo lười biếng khi bạn chọn. Điều đó gửi đi một trong những mối quan tâm của bạn, và những gì "gây ô nhiễm phân cấp kiểu của bạn" thậm chí có nghĩa là gì? –

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