Tôi cần phải lưu trữ một loạt các biến cần phải được truy cập trên toàn cầu và tôi tự hỏi nếu một mẫu đơn sẽ được áp dụng. Từ những ví dụ tôi đã thấy, một mẫu đơn giản chỉ là một lớp tĩnh mà không thể kế thừa được. Nhưng những ví dụ tôi đã thấy quá phức tạp cho nhu cầu của tôi. Điều gì sẽ là lớp singleton đơn giản nhất? Tôi có thể tạo một lớp tĩnh, kín với một số biến bên trong không?Mẫu Singleton cho C#
Trả lời
Thông thường một singleton không phải là một lớp tĩnh - một singleton sẽ cung cấp cho bạn một trường hợp duy nhất của một lớp học.
Tôi không biết những gì ví dụ bạn đã nhìn thấy, nhưng thường là singleton pattern có thể được thực sự đơn giản trong C#:
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
static Singleton() {} // Make sure it's truly lazy
private Singleton() {} // Prevent instantiation outside
public static Singleton Instance { get { return instance; } }
}
Đó không phải là khó khăn.
Lợi thế của một singleton trên các thành viên tĩnh là lớp có thể thực hiện các giao diện vv Đôi khi điều đó hữu ích - nhưng lần khác, các thành viên tĩnh sẽ thực sự làm tốt. Ngoài ra, nó thường dễ dàng hơn để di chuyển từ một singleton sang một singleton không muộn hơn, ví dụ: truyền vào singleton như một đối tượng "cấu hình" cho các lớp phụ thuộc, thay vì các lớp phụ thuộc đó thực hiện các cuộc gọi tĩnh trực tiếp.
Cá nhân tôi cố gắng tránh sử dụng những người độc thân khi có thể - họ làm cho thử nghiệm khó hơn, ngoài bất cứ thứ gì khác. Họ đôi khi có thể hữu ích mặc dù.
Singleton không chỉ là lớp tĩnh không thể được kế thừa. Đó là một lớp thông thường có thể được khởi tạo chỉ một lần, với tất cả mọi người chia sẻ cá thể đơn lẻ đó (và làm cho nó an toàn hơn là công việc nhiều hơn).
Mã .NET điển hình cho Singleton trông giống như sau. Đây là một ví dụ nhanh, và không phải bằng bất kỳ phương tiện thực hiện hoặc thread-safe mã tốt nhất:
public sealed class Singleton
{
Singleton _instance = null;
public Singleton Instance
{
get
{
if(_instance == null)
_instance = new Singleton();
return _instance;
}
}
// Default private constructor so only we can instanctiate
private Singleton() { }
// Default private static constructor
private static Singleton() { }
}
Nếu bạn đang đi để đi xuống con đường bạn đang nghĩ, một lớp kín tĩnh sẽ làm việc bình thường.
Tôi nghĩ rằng bạn cần phải sửa đổi mã đó một chút - và trừ khi bạn cẩn thận trong bản sửa đổi, nó sẽ không an toàn về luồng. Tuy nhiên, làm cho nó thread-an toàn thực sự là khá dễ dàng. –
@Jon Tôi đã không đi cho các phiên bản an toàn thread ở đây. Ví dụ nhanh. Tôi biết một cách để làm cho nó an toàn, nhưng tôi muốn được biết về các bản sửa đổi khác (chỉ vì tò mò). –
Vì vậy, theo như tôi lo ngại, đây là cách triển khai ngắn gọn và đơn giản nhất của mẫu Singleton trong C#.
http://blueonionsoftware.com/blog.aspx?p=c6e72c38-2839-4696-990a-3fbf9b2b0ba4
Tôi sẽ, tuy nhiên, cho rằng độc thân là mô hình thực sự xấu xí ... Tôi coi chúng là một chất chống mẫu.
http://blogs.msdn.com/scottdensmore/archive/2004/05/25/140827.aspx
Đối với tôi, tôi thích có một cái gì đó giống như một kho lưu trữ, thực hiện IRepository. lớp học của bạn có thể khai báo phụ thuộc vào IRepository trong các nhà xây dựng và nó có thể được thông qua việc sử dụng Dependency Injection hoặc một trong các phương pháp:
Có một số mẫu mà có thể thích hợp cho bạn, một singleton là một tồi tệ hơn.
Registry
struct Data {
public String ProgramName;
public String Parameters;
}
class FooRegistry {
private static Dictionary<String, Data> registry = new Dictionary<String, Data>();
public static void Register(String key, Data data) {
FooRegistry.registry[key] = data;
}
public static void Get(String key) {
// Omitted: Check if key exists
return FooRegistry.registry[key];
}
}
Ưu
- Dễ dàng chuyển sang một đối tượng Mock cho tự động kiểm tra
- Bạn vẫn có thể lưu trữ nhiều trường hợp nhưng nếu cần thiết bạn chỉ có một trường hợp .
Nhược
- Hơi chậm hơn so với một Singleton hoặc một biến toàn cầu
tĩnh Lớp
class GlobalStuff {
public static String ProgramName {get;set;}
public static String Parameters {get;set;}
private GlobalStuff() {}
}
Ưu
- Simple
- nhanh
Nhược
- cứng chuyển động để tức là một đối tượng Mock
- cứng để chuyển sang một loại đối tượng nếu yêu cầu thay đổi
Simple Singleton
class DataSingleton {
private static DataSingleton instance = null;
private DataSingleton() {]
public static DataSingleton Instance {
get {
if (DataSingleton.instance == null) DataSingleton.instance = new DataSingleton();
return DataSingleton;
}
}
}
Ưu
- Không thực sự
Nhược
- Khó để tạo singleton chủ đề, Phiên bản trên sẽ không thành công nếu có nhiều chủ đề truy cập cá thể.
- Khó chuyển đổi đối tượng giả
Cá nhân tôi thích Mẫu đăng ký nhưng YMMV.
Bạn nên xem xét Dependency Injection vì nó thường được coi là thực hành tốt nhất nhưng nó quá lớn là một chủ đề để giải thích ở đây.
Tôi nghĩ rằng mô hình singleton của bạn là sai, rằng nếu kiểm tra bên trong của getter không phải là chủ đề an toàn. Bạn muốn thực hiện một singleton như mô tả ở trên bởi @Jon Skeet. Về mặt lý thuyết, 2 luồng có thể nhập getter đó cùng một lúc, cả hai nhìn thấy instance == null và sau đó cả hai thực thi dòng thứ 2 làm cho singleton biến đổi theo luồng cuối cùng. –
@Chris: Tôi đã đề cập rằng việc triển khai này không phải là luồng an toàn trong phần "Nhược điểm". Bộ luật ở đó để giải thích khái niệm, không đưa ra một ví dụ hoàn toàn làm việc. – dbemerlin
@dbemerlin vui lòng sửa mã cho FooRegistry, public static ** Data ** Get (String key) thay vì _void_. Và thực sự cảm ơn cho cái nhìn tổng quan tốt đẹp. –
Sử dụng các tính năng ngôn ngữ của bạn. Triển khai chủ đề an toàn chủ yếu đơn giản là:
public sealed class Singleton
{
private static readonly Singleton _instance;
private Singleton() { }
static Singleton()
{
_instance = new Singleton();
}
public static Singleton Instance
{
get { return _instance; }
}
}
Sử dụng C# 6 Trình khởi chạy tự động thuộc tính.
public sealed class Singleton
{
private Singleton() { }
public static Singleton Instance { get; } = new Singleton();
}
Ngắn gọn và sạch sẽ - Tôi rất sẵn lòng nghe những nhược điểm này.
cho người mới bắt đầu không phải là chủ đề an toàn – JerryGoyal
- 1. Mẫu Singleton trong C++
- 2. C# Mẫu Singleton và MEF
- 3. Đúng đối tượng mẫu Singleton C (iOS)?
- 4. Mẫu Singleton với tham số
- 5. C# Singleton Logging Class
- 6. Mẫu Singleton so với Monostate trong Ruby
- 7. Sử dụng đúng mẫu thiết kế singleton
- 8. Mẫu đăng ký hoặc Singleton trong PHP?
- 9. Tại sao mẫu Borg tốt hơn mẫu Singleton trong Python
- 10. Singleton dùng một lần trong C#
- 11. Mẫu thiết kế Singleton: Cạm bẫy
- 12. Mẫu Singleton: hành vi khác nhau của auto_ptr và unique_ptr
- 13. Mẫu C# singleton đã sửa đổi này có phải là một thực hành tốt không?
- 14. Ví dụ Singleton trong C++/CLI?
- 15. hiệu quả thread-safe singleton trong C++
- 16. Mẫu Singleton Force trên một Lớp thực hiện Giao diện
- 17. Mẫu Singleton - nghi ngờ trong các mẫu thiết kế đầu mẫu đầu tiên
- 18. Bí danh cho mẫu C++?
- 19. Đề xuất cho sách mẫu cho C++?
- 20. Sự khác biệt giữa mẫu thiết kế Singleton và Registry
- 21. System.Lazy <T> và Mẫu thiết kế Singleton
- 22. C# Nhiều trường hợp của một đối tượng Singleton
- 23. Lớp tĩnh vs Singleton
- 24. C# Singleton với hàm tạo chấp nhận tham số
- 25. ASP .NET Singleton
- 26. Trong trường hợp nào chúng ta sử dụng Mẫu Nhà máy và trong đó Mẫu Singleton?
- 27. Doxygen cho C++ mẫu chuyên môn thành viên lớp mẫu
- 28. lớp tĩnh và singleton
- 29. NodeJS - Singleton + Sự kiện
- 30. Mã mẫu C cho Canon EDSDK Liveview?
Giải thích tuyệt vời .... Bạn có thể cho chúng tôi biết một ví dụ (thời gian thực), nơi bạn có thể tìm thấy mẫu đơn giản hữu ích không? +1 – Raja
@Raja: Tôi không thể nghĩ ra bất kỳ tình huống thực sự nào vào lúc này, mặc dù điều đó không có nghĩa là tôi chưa từng sử dụng. –
@Raja đây là một cái gì đó tôi sẽ sử dụng rất nhiều trong .NET 4.0 trong lớp học của tôi mà làm bất kỳ sự phản ánh 'riêng tĩnh readonly ConcurrentDictionary _reflectionCache = new ConcurrentDictionary();' –