2009-07-14 38 views
21

Tôi muốn tạo một lớp tĩnh hoặc lớp singleton chấp nhận tham chiếu đến đối tượng khác trong hàm tạo của nó. Các lớp tĩnh nằm ngoài, nhưng tôi đã hình dung rằng tôi có thể tạo một singleton chấp nhận các tham số trong hàm khởi tạo của nó. Cho đến nay tôi đã không có bất kỳ may mắn tìm ra hoặc googling cú pháp. Điều này có thể không? nếu vậy, làm thế nào để làm điều đó?C# Singleton với hàm tạo chấp nhận tham số

Xin lỗi vì không có ví dụ nào trong bài đăng đầu tiên, tôi đã viết vội vàng. Tôi có cảm giác rằng câu trả lời của tôi đã có trong câu trả lời, nhưng đây là một số làm rõ những gì tôi muốn làm:

Tôi muốn tạo một cá thể đơn lẻ (Singleton), nhưng loại cần giữ một tham chiếu đến một đối tượng khác.

Ví dụ: tôi có thể muốn tạo lớp "Trạng thái" Singleton, lớp này sở hữu đối tượng StringBuilder và phương thức Draw() có thể được gọi để viết StringBuilder cho màn hình. Phương thức Draw() cần biết về GraphcisDevice của tôi để vẽ. Vì vậy, những gì tôi muốn làm điều đó này:

public class Status 
{ 
private static Status _instance; 
private StringBuilder _messages; 
private GraphicsDevice _gDevice; 

private Status(string message, GraphicsDevice device) 
{ 
    _messages.Append(message); 
    _gDevice = device; 
} 

// The following isn't thread-safe 

// This constructor part is what I'm trying to figure out 
public static Status Instance // (GraphicsDevice device) 
    { 
    get 
     { 
     if (_instance == null) 
      { 
      _instance = new Status("Test Message!", device); 
      } 
     return _instance; 
     } 
    } 

public void UpdateMessage 
... 

public void Draw() 
    { 
    // Draw my status to the screen, using _gDevice and _messages 
    } 
} 

Khắp mã, tôi lấy Tình trạng của tôi Singleton và gọi phương thức của nó UpdateMessage().

private Status _status = Status.Instance; // + pass reference to GraphicsDevice 
_status.UpdateMessage("Foo!"); 

Sau đó, trong lớp học chính của tôi, tôi cũng lấy singleton, và vẽ nó:

_status.Draw(); 

Vâng, điều này có nghĩa rằng bất cứ nơi nào tôi lấy singleton, tôi cần phải làm như vậy bằng cách đi qua trong tham chiếu đến GraphicsDevice, trong trường hợp đó là lần đầu tiên tôi khởi tạo Singleton. Và tôi có thể sử dụng các phương tiện khác nhau để lấy một thứ gì đó cơ bản như GraphicsDevice trong lớp Singleton của tôi, ví dụ như đăng ký một dịch vụ ở nơi khác và nhận dịch vụ đó trong lớp Trạng thái. Ví dụ này đã khá giả tạo - Tôi đang cố gắng tìm hiểu xem có phải điều gì đó như mẫu này có thể thực hiện được không.

+1

Đã thêm giải thích tốt hơn về những gì tôi đã hỏi. –

Trả lời

2

Những gì bạn mô tả là Chung Singleton. Nó trông giống như thế này:

public class SingletonProvider <T> where T:new() 
{ 
    SingletonProvider() {} 

    public static T Instance 
    { 
     get { return SingletonCreator.instance; } 
    } 

    class SingletonCreator 
    { 
     static SingletonCreator() { } 

     internal static readonly T instance = new T(); 
    } 
} 

http://www.codeproject.com/KB/cs/genericsingleton.aspx

+4

Làm thế nào bạn có thể đảm bảo rằng không có bất kỳ trường hợp nào khác của loại T trong ứng dụng của bạn? Đây không hẳn là một singleton. –

+5

Tôi cho rằng người hỏi câu hỏi đã hiểu rằng anh ta không thể sử dụng loại cho bất cứ điều gì khác. Anh ta hỏi con dao, tôi không bảo anh ta phải làm gì với nó. –

+1

Singleton là loại khác với Singleton , vì vậy không quan trọng. Chung singleton chỉ có ý nghĩa nếu chúng phục vụ như là một lớp cơ sở để tạo ra các singletons, tôi tưởng tượng. –

17

này thường được coi là một ý tưởng tồi bởi vì nếu bạn đang đi để chấp nhận hoặc là một tham chiếu đối tượng hoặc một đối số kiểu mà bạn có kế hoạch gói trong một wrapper singleton giống như bạn không thể đảm bảo rằng bạn giữ trường hợp duy nhất của loại đó trong AppDomain.

Toàn bộ điểm của mẫu đơn là để điều khiển một thể hiện đơn của một loại để chỉ một thể hiện kiểu đó có thể tồn tại. Nếu bạn cho phép một thể hiện được chuyển vào hoặc nếu bạn tạo một nhà cung cấp singleton chung, bạn không thể đảm bảo rằng cá thể của bạn là chỉ là cá thể.

Giả sử tôi có một số SingletonFactory<T> để cho phép tôi tạo một bản đơn xung quanh bất kỳ loại nào mà tôi chuyển đến nhà máy.Đó sẽ là khá tiện dụng và sẽ cho phép tôi làm điều gì đó như thế này:

SingletonFactory<Foo>.Instance; 

Nhưng những gì đang ngăn cản tôi từ cũng làm điều này:

Foo foo = new Foo(); 

Rất tiếc, có vẻ như Foo không phải là một singleton nữa vì tôi có thể tạo bao nhiêu lần như tôi muốn. Để mô hình singleton hoạt động, bạn cần có khả năng kiểm soát hoàn toàn loại có các trường hợp bạn cần hạn chế. Đây là lý do tại sao bạn không nên sử dụng bất cứ thứ gì như số SingletonFactory<T> của tôi.

Lưu ý:Cũng vậy với một singleton không chung chung chấp nhận một cá thể đối tượng. Tôi chắc chắn rằng bạn có thể ngoại suy từ ví dụ trước của tôi nhiều lý do tương tự tại sao một wrapper singleton chấp nhận và tham chiếu đối tượng cũng sẽ là một ý tưởng tồi.

2

Những gì bạn đang đặc biệt yêu cầu ngoại hình như thế này, tôi nghĩ rằng:

public sealed class Singleton { 
    static Singleton instance = null; 
    static readonly object padlock = new Object(); 
    Object o; 

    Singleton(Object _o) { 
     o = _o; 
    } 

    public static Singleton Instance(Object _o) { 
     lock (padlock) { 
      if (instance == null) { 
       instance = new Singleton(_o); 
      } 
      return instance; 
     } 
    } 
} 

Singleton s = Singleton.Instance(new Object()); 

tôi nghi ngờ rằng phiên bản generic đã được đăng là những gì bạn thực sự muốn, mặc dù.

1

Bạn cần một hàm tạo riêng và sau đó là phương thức getInstance, phương thức này là người sẽ nhận được tham số, hàm tạo phải là riêng và nó cũng có thể có tham số, nhưng getInstance sẽ vượt qua nó, không có bạn. Btw, bạn đang làm gì? Một số ví dụ thực sự có thể giúp bạn.

0

Một điều bạn có thể làm có thể được gắn bó với mẫu singleton bạn tìm thấy và chỉ để lộ một tài sản (setter, nếu cần thiết, thêm getter cũng) và sử dụng nó như MySingleton.Instance.MyReference = new MyObject();

Nếu bạn cần phải hạn chế sử dụng đối tượng singleton của bạn, ví dụ, bất kỳ thao tác nào trên đối tượng singleton trước khi tham chiếu được đặt cần phải là bất hợp pháp, bạn có thể có cờ boolean riêng, ví dụ, hasBeenIntialized và MyReference setter sẽ đặt cờ bên trong. Tất cả các phương thức khác sẽ kiểm tra cờ ở đầu của việc thực hiện và ném một ngoại lệ nếu bất kỳ phương thức nào được gọi nếu hasBeenInitialized là sai.

Nếu bạn cần có hành vi chỉ đọc, bạn có thể ném ngoại lệ trong trình thiết lập MyReference nếu có ai đó muốn gán một đối tượng khác trong khi hasBeenInitialized được đặt thành true.

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