代码之家  ›  专栏  ›  技术社区  ›  Pierreten

Doubleton模式实现

  •  1
  • Pierreten  · 技术社区  · 16 年前

    我在利用Doubleton模式 the Doubleton Design Pattern on Code Project 用我自己的代码。我认为这会使事情变得容易很多,因为单例程序只提供一个实例,但是我用这个模式得到了两个实例。我想知道让它实现一个接口是否有意义,这样我就可以将它注入到我的域层中。

    3 回复  |  直到 16 年前
        1
  •  3
  •   Humberto    16 年前

    尽管这种设计很有用,也很聪明,但它是不可能的。不能在接口中定义静态成员。

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

    @Pierreten,如果您使用实例方法,请想象一下:

    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?
    

    编辑:正如@roger pate正确指出的那样,我的第二个答案应该合并到这个答案中。因为他已经这样做了,我删除了另一个。

        2
  •  1
  •   Nate Pinchot    16 年前

    对这个答案的澄清:这并不完全解决 问题 被问到,但是与上面相关的实现被可怕地编码了。也许下面的实现是线程安全的。

    我不能百分之百地肯定这是线程安全的,因为我没有测试它(而且我不能想出任何实际使用这个“模式”的方法,因为我认为它很混乱),但是它是一个更正确的单例实现,它是您链接到上面的内容的,并且可能工作来完成您想要的内容。祝你好运。

    很抱歉 Console.WriteLine() 调用时,我使用代码片段编译器来完成此操作。

    /// <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;
        }
    }
    

    然后可以使用以下代码:

    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());
    }
    
        3
  •  0
  •   Cade Roux    16 年前

    我认为很难看到这样一个类的使用,但是,我有一个用于singleton的通用类-我认为它可以被修改/扩展-您可以从接口中获得一些好处:

    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;
    }