views:

367

answers:

3

I'm leveraging the Doubleton 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.

+3  A: 

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.

Humberto
Okay, should I make it an instance method?
Pierreten
first of all it looks as a joke. second is that what could be called as Doubleton is customized version of Object Pool
Andrey
+1  A: 

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());
}
Nate Pinchot
Snippet Compiler? You need to get yourself some LINQPad. Saves me so much time every single day!
John
I can't see in any way how this is relevant to the question asked
fearofawhackplanet
The Doubleton pattern implementation he linked to was poorly coded, so I was trying to help him with one that might work better. How is it irrelevant?
Nate Pinchot
Because the question is about whether the pattern could/should implement an interface.
fearofawhackplanet
Right but he is "leveraging the Doubleton Pattern from the Doubleton Design Pattern on Code Project in my own code". The one he is using is very broken and definitely not thread safe. So I was trying to help him have a more correct implementation. While it does not answer the question, I still don't think that makes it irrelevant to his situation. I was just trying to help the guy out (isn't that what SO is about?). Forgive me, please.
Nate Pinchot
Ok, maybe you should mention that in your answer then. I didn't read the Code Project code (I can't honestly imagine any use of the pattern).
fearofawhackplanet
Fair enough :) I updated the answer. I can't imagine any use of the pattern either, and when I asked him he didn't provide one - but he seemed dead set on using it, so I figured it would be better if he actually used a more properly coded Singleton-like implementation :)
Nate Pinchot
A: 

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;
}
Cade Roux
is it singleton at all? it creates instance on each call
Andrey
@Andrey - Sure: public class X : SingletonBase<X> { /* implementation here */ } makes X a singleton (private constructors and all).
Cade Roux