开发者

Doubleton Pattern Implementation

I'm leveraging the Doubleto开发者_C百科n Pattern from the Doubleton Design Pattern on Code Project in my own code. I think it makes things a lot easier since the Singleton only provides one instance, but I get two with this pattern. I was wondering if it would make sense to have it implement an interface so I can inject it into my domain layer.


Despite the usefulness and cleverness of such design, it is not possible. You can't define a static member in an interface.

public interface IDoubleton
{
    static IDoubleton Instance { get; } // Can't be done
}

@Pierreten, If you use instance methods, imagine this:

IDoubleton firstInstance;
// Construct firstInstance,
// do some stuff...

// Now comes trouble.
IDoubleton secondInstance = firstInstance.Instance; // what does it mean?
IDoubleton anotherInstance = secondInstance.Instance.Instance.Instance; // what now?

EDIT: As @Roger Pate rightfully pointed out, my 2nd answer should be merged within this one. As he already had done it, I deleted the other one.


Clarification on this answer: This doesn't exactly address the question asked, but the implementation that was linked to above is horribly coded. Perhaps the implementation below would be thread safe.

I'm not 100% sure that this is thread safe because I did not test it (and I can't come up with any real world use of this "pattern" because I think it is confusing), but it is a more correct Singleton-like implementation of what you linked to above and might work to accomplish what you wanted. Good luck.

Sorry about the Console.WriteLine() calls, I used Snippet Compiler to make this.

/// <summary>
/// Doubleton
/// </summary>
public sealed class Doubleton
{
    const int MaxInstances = 2;
    static volatile Hashtable instances = new Hashtable();
    static volatile int PreviousInstanceNumber = MaxInstances;

    #region Constructor
    Doubleton()
    {
    }
    #endregion

    #region Properties
    /// <summary>
    /// Get 1 of 2 instances of a Doubleton
    /// </summary>
    public static Doubleton Instance
    {
        get
        {
            lock (instances.SyncRoot)
            {
                int instanceNumber = PreviousInstanceNumber == MaxInstances ? 1 : ++PreviousInstanceNumber;

                // if it doesn't exist, create it
                if (instances[instanceNumber] == null)
                {
                    instances[instanceNumber] = new Doubleton();
                }

                PreviousInstanceNumber = instanceNumber;

                return (Doubleton)instances[instanceNumber];
            }
        }
    }
    #endregion

    /// <summary>
    /// Get the index of the Doubleton
    /// </summary>
    /// <returns></returns>
    public int GetInstanceIndex()
    {
        lock (instances.SyncRoot)
        {
            for (int i = 1; i <= MaxInstances; i++)
            {
                if (instances[i] != null && instances[i].Equals(this))
                {
                    return i;
                }
            }
        }

        return -1;
    }
}

You could then use the following code:

var instance1 = Doubleton.Instance;
var instance2 = Doubleton.Instance;

var instance1Again = Doubleton.Instance;
var instance2Again = Doubleton.Instance;

Console.WriteLine("The following 2 lines should be true:");
Console.WriteLine(instance1.Equals(instance1Again));
Console.WriteLine(instance2.Equals(instance2Again));

Console.WriteLine("---");
Console.WriteLine("The next 50 lines should alternate instances:");
for (int i = 0; i < 50; i++)
{
    var instance = Doubleton.Instance;
    Console.WriteLine("I have instance # " + instance.GetInstanceIndex());
}


I think it is difficult to see the use of such a class, however, I have a generic class I use for Singleton - I imagine it could be modified/extended - you get some of the benefits of an interface:

public class SingletonBase<T> where T : class
{
    static SingletonBase()
    {
    }

    public static readonly T Instance = 
        typeof(T).InvokeMember(typeof(T).Name, 
                                BindingFlags.CreateInstance | 
                                BindingFlags.Instance |
                                BindingFlags.Public |
                                BindingFlags.NonPublic, 
                                null, null, null) as T;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜