2010-06-03 49 views
33

Khi nào một singleton thực sự dễ dàng hơn hoặc tốt hơn một lớp tĩnh? Dường như với tôi tạo ra một singleton chỉ là nỗ lực thêm mà không thực sự cần thiết, nhưng tôi chắc chắn có một lý do chính đáng. Nếu không, họ sẽ không được sử dụng, rõ ràng.Tại sao sử dụng singleton thay vì lớp tĩnh?

Trả lời

22

Một lý do chính đáng để chọn một singleton trên một lớp tĩnh (giả sử bạn không có mẫu nào tốt hơn theo ý của bạn;)), đang hoán đổi một thể hiện đơn với nhau.

Ví dụ, nếu tôi có một lớp khai thác gỗ như thế này:

public static class Logger { 
    public static void Log(string s) { ... } 
} 

public class Client { 
    public void DoSomething() { 
     Logger.Log("DoSomething called"); 
    } 
} 

Nó hoạt động thực sự tốt, nhưng những gì nếu Logger viết điều cần một cơ sở dữ liệu, hoặc viết ra để giao diện điều khiển.Nếu bạn đang viết kiểm tra, có thể bạn không muốn tất cả những tác dụng phụ đó - nhưng vì phương thức log là tĩnh, bạn không thể làm bất cứ điều gì ngoại trừ.

Ok, vì vậy tôi muốn trao đổi nóng phương thức Đăng nhập của mình để thử nghiệm. Đi đi tiện ích singleton!

public class Logger { 
    private static Logger _instance; 
    public static Logger Instance 
    { 
     get 
     { 
      if (_instance == null) 
       _instance = new Logger(); 
      return _instance; 
     } 
     set { _instance = value; } 
    } 
    protected Logger() { } 
    public virtual void Log(string s) { ... } 
} 

public class Client { 
    public void DoSomething() { 
     Logger.Instance.Log("DoSomething called"); 
    } 
} 

Vì vậy, bạn có thể định nghĩa một TestLogger : Logger với một phương pháp rỗng Log, sau đó thiết lập một thể hiện của logger thử nghiệm của bạn đến thể hiện singleton để kiểm tra. Mau! Bạn có thể hotswap thực hiện logger của bạn để kiểm tra hoặc sản xuất mà không ảnh hưởng đến mã máy khách.

10

Singletons thường được ưa thích cho các biến toàn cầu vì:

  • Họ không làm ô nhiễm không gian tên toàn cầu (hoặc, trong ngôn ngữ với không gian tên, không gian tên chứa của họ) với các biến không cần thiết.
  • Chúng cho phép phân bổ và khởi tạo lười biếng, trong khi các biến toàn cầu bằng nhiều ngôn ngữ sẽ luôn luôn tiêu thụ tài nguyên.

Source

EDIT:

Một sử dụng mát của singleton là, khi kết hợp với các phương pháp nhà máy, có thể được sử dụng để tạo ra các Flyweight pattern. Đây là khi bạn tạo một đối tượng mới, Factory (thay vì tạo một đối tượng mới) đầu tiên kiểm tra để xem một singleton của đối tượng đó đã được tạo, nếu có, nó chỉ trả về đối tượng đó, nếu không, nó sẽ tạo ra một singleton mới và trả về điều đó, theo dõi các single mà nó tạo ra. Flyweights làm việc vì sự bất biến của singleton.

+1

hạng ruồi là giống như một "multiton", không phải thực sự là một singleton. – BalusC

+0

Multiton ... Tôi thích nó! –

+2

Nó tồn tại. Xem [wikipedia] (http://en.wikipedia.org/wiki/Multiton_pattern). – BalusC

2

Singletons duy trì cách tiếp cận lớp học thông thường, và không yêu cầu bạn phải sử dụng từ khoá tĩnh ở khắp mọi nơi. Họ có thể đòi hỏi nhiều hơn để thực hiện lúc đầu, nhưng sẽ đơn giản hóa rất nhiều kiến ​​trúc của chương trình của bạn. Không giống như các lớp tĩnh, chúng ta có thể sử dụng singletons làm tham số hoặc đối tượng.

Ngoài ra, bạn có thể sử dụng các trình đơn có giao diện giống như bất kỳ lớp nào khác.

3

Mặc dù IMHO Singleton pattern là một mô hình chứ không phải lạm dụng, nó đôi khi mang lại lợi ích, chẳng hạn như:

  • Khả năng sử dụng các loại khác nhau của các đối tượng (mà kế thừa từ các cơ sở giống nhau) như trường hợp (nghĩ rằng các nhà cung cấp dữ liệu trong đó một nhà cung cấp sử dụng hệ thống tập tin và một cơ sở dữ liệu SQL, ví dụ)
  • Khả năng nối tiếp. Tôi đã không sử dụng một khuôn khổ có thể tự động tuần tự hóa các lớp tĩnh.
  • Sử dụng các trường ít tĩnh hơn. Đối với một số người, đây là một tính năng thẩm mỹ, nhưng trong một số trường hợp, nó có lợi ích thiết thực.
5

Singletons luôn có vẻ hơi dư thừa đối với tôi. Tôi thích các lớp tĩnh, và nếu tôi cần hành vi khác nhau, tôi kết hợp nó với một tiêm phụ thuộc và một nhà cung cấp .. Tôi không biết mô hình này là gì, hoặc nếu nó có tên, nhưng nó thường đi như sau:

public interface IFooProvider { 
    Bar FooBar(); 
} 

public static class Foo { 
    public static readonly IFooProvider FooProvider { get; set; } 
    public Bar FooBar() { return FooProvider.FooBar(); } 
} 

Sau đó, tôi chỉ cần đảm bảo đặt nhà cung cấp ở đâu đó trong phương pháp init của tôi. Thật dễ dàng để thêm khởi tạo lười biếng nếu bạn muốn bằng cách thiết lập nhà cung cấp mặc định khi khởi tạo lớp. Hay nhất của tất cả, nó cho phép bạn thay đổi hành vi trong khi vẫn nhận được thẩm mỹ của việc sử dụng các lớp tĩnh.

1
  1. Một Singleton có thể thực hiện các giao diện, kế thừa từ các lớp khác
  2. Một Singleton có thể được khởi tạo lười biếng hoặc không đồng bộ và nạp tự động bởi .NET Framework CLR (phổ biến thời gian chạy ngôn ngữ) khi chương trình hay không gian tên có chứa các lớp nạp vào. Trong khi một lớp tĩnh thường được khởi tạo khi nó được nạp lần đầu và nó sẽ dẫn đến các vấn đề về trình nạp lớp tiềm năng.
  3. Lớp Singleton tuân theo Nguyên tắc hướng đối tượng
  4. Đối tượng Singleton được lưu trữ trên heap trong khi lớp tĩnh được lưu trữ trong ngăn xếp.
  5. Đối tượng Singleton có thể có hàm tạo trong khi Lớp tĩnh không thể.
  6. Singleton đối tượng có thể vứt bỏ nhưng không phải lớp tĩnh
  7. Singleton đối tượng có thể sao chép nhưng không phải với lớp tĩnh
Các vấn đề liên quan