2010-05-04 61 views
68

Tôi chưa bao giờ tìm thấy câu trả lời hay cho các câu hỏi đơn giản về lớp trợ giúp/tiện ích:Tại sao sử dụng singleton thay vì phương pháp tĩnh?

Tại sao tôi tạo một singleton (không quốc tịch) thay vì sử dụng các phương pháp tĩnh?

Tại sao một đối tượng đối tượng lại cần thiết nếu đối tượng không có trạng thái?

+0

có thể trùng lặp của http://stackoverflow.com/questions/720744/static-class-and-singleton –

+0

Đừng nghĩ vì chúng ta nói về 2 ngôn ngữ khác nhau nên câu trả lời có thể thay đổi, nhưng cảm ơn vì liên kết, trong java không bao giờ nghe thuật ngữ "monostate" –

Trả lời

64

Một singleton được sử dụng để giới thiệu một số trạng thái toàn cầu toàn cầu cho một ứng dụng. Nếu nó là quốc tịch, tôi cũng không nhìn thấy điểm của việc sử dụng một singleton, trừ khi

  • bạn mong đợi để mở rộng nó với nhà nước trong tương lai gần hoặc
  • bạn cần một đối tượng dụ đối với một số đặc biệt lý do kỹ thuật (ví dụ: đối với câu lệnh C# lock, mặc dù điều này đã khá được tìm nạp) hoặc
  • bạn cần thừa kế, nghĩa là bạn có thể dễ dàng thay thế singleton của mình bằng cách sử dụng cùng giao diện khác nhưng thực hiện khác. Ví dụ, phương thức Toolkit.getDefaultToolkit() trong Java sẽ trả về một singleton có kiểu chính xác phụ thuộc vào hệ thống.
+23

Tôi sẽ đi với +1, mặc dù IMHO singletons được ** sử dụng sai ** để giới thiệu các quốc gia toàn cầu. Mục đích của một singleton không phải là để làm cho một đối tượng trên toàn cầu có sẵn, nhưng để thực thi rằng một đối tượng được khởi tạo chỉ một lần. Đối tượng toàn cầu là một điều ác cần thiết. Trừ khi thực sự cần thiết, người ta nên cố gắng không sử dụng chúng, vì họ thường dẫn đến khớp nối cao, với SomeSingleton.getInstance(). SomeMethod() tất cả các nơi.:) – back2dos

+0

Nó có thể hữu ích trong các trò chơi mà bạn chỉ muốn một bản sao hiển thị thay vì nhiều bản sao hiển thị hoặc với lớp đường ống mạng nơi bạn thiết lập kênh bảo mật chỉ có thể có một kết nối tại một thời điểm. – Tschallacka

+2

"dễ dàng thay thế singleton của bạn" một phần là điểm quan trọng nhất trong quan điểm của tôi. Phần còn lại là khá gần với thực hiện lớp tĩnh. –

34

Tôi có thể thấy một trường hợp cho một singleton không trạng thái được sử dụng thay vì một lớp phương thức tĩnh, cụ thể là Dependency Injection.

Nếu bạn có một lớp trợ giúp của các hàm tiện ích mà bạn đang sử dụng trực tiếp, nó tạo ra một phụ thuộc ẩn; bạn không thể kiểm soát ai có thể sử dụng nó, hoặc ở đâu. Việc tiêm cùng một lớp trợ giúp đó thông qua một cá thể singleton không quốc tịch cho phép bạn kiểm soát vị trí và cách nó được sử dụng, và thay thế nó/giả lập nó/vv khi bạn cần.

Làm cho nó trở thành một trường hợp đơn lẻ chỉ đơn giản là đảm bảo rằng bạn không phân bổ bất kỳ đối tượng nào của loại hơn mức cần thiết (vì bạn chỉ cần một).

+1

* "bạn không thể kiểm soát ai có thể sử dụng nó, hoặc ở đâu." * Tại sao ai đó cần nó? – hagrawal

+0

@hagrawal cho mục đích thử nghiệm, bạn sẽ có thể thử nó –

5

Trong hầu hết các lớp ngôn ngữ lập trình, có rất nhiều loại hệ thống. Trong khi một lớp, với các phương thức tĩnh và các biến của nó là một đối tượng, nó thường không thể thực hiện một giao diện hoặc mở rộng các lớp khác. Vì lý do đó, nó không thể được sử dụng theo cách đa hình, vì nó không thể là kiểu con của kiểu khác. Ví dụ, nếu bạn có một giao diện IFooable, được yêu cầu bởi một số chữ ký phương thức của các lớp khác, đối tượng lớp StaticFoo không thể được sử dụng thay cho IFooable, trong khi FooSingleton.getInstance() có thể (giả sử, FooSingleton thực hiện IFooable).

Xin lưu ý rằng, như tôi đã nhận xét về câu trả lời của Heinzi, một singleton là một mẫu để kiểm soát sự kiện. Nó thay thế new Class() bằng Class.getInstance(), cho phép tác giả kiểm soát nhiều hơn các trường hợp mà ông có thể sử dụng để ngăn chặn việc tạo các trường hợp không cần thiết. Singleton chỉ là một trường hợp rất đặc biệt của mẫu nhà máy và cần được xử lý như vậy. Việc sử dụng phổ biến làm cho nó trở thành trường hợp đặc biệt của các đăng ký toàn cầu, thường kết thúc là xấu, bởi vì các đăng ký toàn cầu không nên được sử dụng một cách đơn giản.

Nếu bạn có kế hoạch cung cấp các hàm trợ giúp toàn cầu, thì các phương thức tĩnh sẽ hoạt động tốt. Lớp sẽ không hoạt động như lớp, mà đúng hơn là một vùng tên. Tôi đề nghị, bạn duy trì sự gắn kết cao, hoặc bạn có thể kết thúc với các vấn đề ghép nối kỳ lạ nhất.

Greetz
back2dos

0

Singleton không quốc tịch, nó giữ trạng thái toàn cầu.

Một số lý do mà tôi có thể nghĩ đến sử dụng Singleton là:

  • Để tránh rò rỉ bộ nhớ
  • Cung cấp tình trạng tương tự cho tất cả các module trong một kết nối cơ sở dữ liệu ứng dụng ví dụ
+0

Tôi biết nhưng thực sự một singleton có thể nhiều hơn hoặc ít hơn là không quốc tịch ... Nếu nó không chia sẻ bất kỳ thuộc tính lớp ... –

11

Thật sự tôi đã tìm thấy một câu trả lời khác không được đề cập ở đây: các phương pháp tĩnh khó kiểm tra hơn.

Có vẻ như hầu hết các khung kiểm thử đều hoạt động tốt cho các phương thức mô phỏng, nhưng nhiều trong số chúng không xử lý một cách phong nha giả lập các phương thức tĩnh.

+2

Nhưng Powermock dường như có thể làm như vậy –

2

Có sự cân bằng giữa việc sử dụng cái nào. Singletons có thể hoặc có thể không có nhà nước và họ đề cập đến các đối tượng. Nếu họ không giữ trạng thái và chỉ được sử dụng để truy cập toàn cục, thì tĩnh là tốt hơn vì các phương thức này sẽ nhanh hơn. Nhưng nếu bạn muốn sử dụng các đối tượng và khái niệm OOP (đa hình thừa kế), thì singleton là tốt hơn.

Hãy xem xét một ví dụ: java.lang.Runtime là một lớp đơn trong java. Lớp này cho phép các triển khai khác nhau cho mỗi JVM. Việc triển khai thực hiện đơn trên mỗi JVM. Nếu lớp này sẽ là tĩnh, chúng ta không thể vượt qua các triển khai khác nhau dựa trên JVM.

Tôi thấy liên kết này thực sự hữu ích: http://javarevisited.blogspot.com/2013/03/difference-between-singleton-pattern-vs-static-class-java.html?

Hy vọng điều đó sẽ hữu ích !!

+0

Câu trả lời này là tốt để bao gồm một ví dụ cụ thể trong thế giới thực. – systemovich

1

Đối với tôi "Muốn Object Nhà nước sử dụng Singleton, Muốn Chức năng sử dụng phương pháp tĩnh"

Nó phụ thuộc vào những gì bạn muốn. Bất cứ khi nào bạn muốn trạng thái đối tượng (ví dụ: Đa hình như trạng thái Null thay vì null hoặc trạng thái mặc định), singleton là lựa chọn thích hợp cho bạn trong khi phương pháp tĩnh sử dụng khi bạn cần chức năng (Nhận đầu vào rồi trả về đầu ra).

Tôi đề xuất cho trường hợp đơn lẻ, nó phải luôn ở trạng thái giống nhau sau khi được khởi tạo. Nó không được nhân bản, cũng như không nhận được bất kỳ giá trị nào được đặt thành (ngoại trừ cấu hình tĩnh từ tệp, ví dụ: thuộc tính tệp trong java).

P.S. Hiệu suất giữa 2 lần này khác nhau theo mili giây, do đó, hãy tập trung vào Kiến trúc trước tiên.

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