2010-04-06 6 views
8

Tôi đã gặp sự cố hôm nay và một người bạn đề nghị tôi sử dụng một trường hợp tĩnh toàn cầu hoặc mẫu đơn giản hơn thanh lịch. Tôi đã dành một vài giờ đọc về những người độc thân nhưng một vài điều vẫn còn thoát khỏi tôi.Sử dụng singleton thay vì một thể hiện tĩnh toàn cầu

Bối cảnh: Việc cố gắng thực hiện là tạo một thể hiện của một API và sử dụng cá thể này trong tất cả các lớp của tôi (trái ngược với việc tạo kết nối mới, v.v.).

Dường như có khoảng 100 cách tạo Singleton nhưng với một số trợ giúp từ yoda Tôi đã tìm thấy một số ví dụ về an toàn chủ đề. ..so được cung cấp mã sau:

public sealed class Singleton 
{ 
    public static Singleton Instance { get; private set; } 

    private Singleton() 
    { 
     APIClass api = new APIClass(); //Can this be done? 
    } 

    static Singleton() { Instance = new Singleton(); } 
} 

Làm thế nào/Bạn sẽ khởi tạo lớp mới này ở đâu và cách gọi từ lớp riêng?

EDIT: Tôi nhận ra lớp Singleton có thể được gọi với một cái gì đó giống như

Singleton obj1 = Singleton.Instance(); 

nhưng tôi sẽ có thể truy cập các phương pháp trong lớp API (tức obj1.Start.)? (không phải tôi cần, chỉ cần hỏi)

EDIT # 2: Tôi có thể đã hơi sớm trong việc kiểm tra câu trả lời nhưng tôi có một điều nhỏ mà vẫn gây ra vấn đề cho tôi. API đang khởi chạy tốt, đáng tiếc là Im có thể khởi chạy hai phiên bản?

Mã New

public sealed class SingletonAPI 
{ 
public static SingletonAPI Instance { get; private set; } 

private SingletonAPI() {} 

static SingletonAPI() { Instance = new SingletonAPI(); }  

// API method: 
public void Start() { API myAPI = new API();} 
} 

nhưng nếu tôi cố gắng làm một cái gì đó như thế này ...

SingletonAPI api = SingletonAPI.Instance; 
api.Start(); 
SingletonAPI api2 = SingletonAPI.Instance; // This was just for testing. 
api2.Start(); 

tôi nhận được một thông báo lỗi rằng tôi không thể bắt đầu nhiều hơn một ví dụ.

+4

Bạn nên hãy thêm một hàm tạo riêng, để ngăn chặn một lớp khác khởi tạo một bản sao Singleton của bạn. –

+0

Cảm ơn bạn, tôi đã bỏ lỡ điều đó. – Ryan

+0

Bạn sẽ không thể gọi các phương thức trên lớp api vì nó không bị lộ. –

Trả lời

9

Tại sao không chỉ thêm thuộc tính APIClass công khai vào singleton của bạn?

public sealed class Singleton 
{ 
    public static Singleton Instance { get; private set; } 

    private APIClass _APIClass; 

    private Singleton() 
    { 
     _APIClass = new APIClass(); 
    } 

    public APIClass API { get { return _APIClass; } } 

    static Singleton() { Instance = new Singleton(); }  
} 

Sau đó trang web gọi điện thoại của bạn trông giống như:

Singleton.Instance.API.DoSomething(); 

Hoặc nếu bạn là tác giả của lớp API, bạn có thể biến nó thành một singleton chính nó, thay vì gói nó trong một singleton:

public sealed class SingletonAPI 
{ 
    public static SingletonAPI Instance { get; private set; } 

    private SingletonAPI() {} 

    static SingletonAPI() { Instance = new SingletonAPI(); }  

    // API method: 
    public void DoSomething() { Console.WriteLine("hi"); } 
} 

gọi API:

SingletonAPI.Instance.DoSomething(); 
+1

@charles Cảm ơn bạn rất nhiều, đó chính xác là những gì tôi cần. – Ryan

3

Bạn sẽ không khởi tạo lớp - mẫu bạn đang sử dụng về cơ bản sẽ tự khởi chạy ngay lần đầu tiên được sử dụng. Ưu điểm của phương thức mà bạn đang sử dụng là thread của nó an toàn (sẽ chỉ khởi tạo một lần, cho dù có bao nhiêu luồng truy cập nó), lười (nó sẽ không khởi tạo cho đến khi bạn truy cập lớp Singleton) và đơn giản trong thực hiện.

Tất cả bạn cần làm gì để sử dụng này là để làm:

Singleton.Instance.MyMethodOnSingleton(); 

Hoặc cách khác:

Singleton myInstance = Singleton.Instance; // Will always be the same instance... 
myInstance.DoSomething(); 
+0

tôi cũng khuyên bạn nên đọc Farstucker về các singletons trên msdn http://msdn.microsoft.com/en-us/library/ms998558.aspx – vittore

+0

Tin hay không, tôi đã đọc nó. Tôi đoán Im chỉ bối rối về cách tạo ra một lớp hoàn toàn khác và sử dụng nó trên toàn cầu. Tôi đã thêm một số mã để giúp giải thích những gì Im đang cố gắng làm. – Ryan

5

Đây là official Microsoft approach.

Vẻ đẹp của singleton là bạn có thể sử dụng và truy cập nó ở bất cứ nơi nào trong mã của bạn mà không cần phải tạo một thể hiện của lớp. Trong thực tế có nghĩa là nó raison d'être, một trường hợp duy nhất của một lớp ví dụ

Singleton.Instance.MyValueSingleton.Instance.DoSomething();