更简单的单身模式

时间:2015-03-30 09:28:17

标签: c# design-patterns singleton

我一直在审查一些旧项目的代码,我在那里找到了一个单身人士。这是一个要求使用单身人士,我正在考虑一种让它看起来更简单的方法"使用时。

我发现,访问像静态类这样的方法和属性会更容易。所以我基本上使用静态方法实现了单例,以跳过使用GetInstance()的要求。这就是我实现它的方式:

public class ExampleSingleton
{
    string someRequiredValue = "This is an example.";

    /// <summary>
    /// Private Constructor
    /// </summary>
    private ExampleSingleton() { }
    private static volatile ExampleSingletoninstance;

    /// <summary>
    /// !!! PRIVATE !!!
    /// Instance Property.
    /// Returns the instance of this singleton.
    /// (ThreadSafe)
    /// </summary>
    private static ExampleSingleton Instance
    {
        get
        {
            if (instance == null)
            {
                lock (_lock)
                {
                    if (instance == null)
                    {
                        instance = new ExampleSingleton();
                    }
                }
            }

            return instance;
        }
    }

    /// <summary>
    /// Example field contains a value that should be
    /// accessible from outside.
    /// </summary>
    public static string SomeRequiredField
    {
        get
        {
            // Here you do the job you would have to do "outside"
            // of the class normally.
            return ExampleSingleton.Instance.someRequiredValue;
        }
    }

    // Helper for a secure thread synchronisation.
    private static object _lock = new object();
}

因此,当您想要访问单例值时,您可以这样做:

// Access the values like this
string requiredField = ExampleSingleton.SomeRequiredField;

// Instead of this
string requiredField = ExampleSingleton.Instance.SomeRequiredField;

// Or even this
string requiredField = ExampleSingleton.GetInstance().SomeRequiredField;

我是否违反了单身人士模式的原则?它基本上仍然是一个单例模式,但获取实例的工作是在内部完成的。这个例子的概念可能是什么?还有其他职业选手吗?

由于

2 个答案:

答案 0 :(得分:3)

就缺点而言,过去有两个人咬过我:

  1. 由于吸气剂是静止的
  2. ,很难嘲笑单身人士
  3. 对单件界面的更改需要进行2次单独更改(一次针对公共静态,一种针对内部界面)。
  4. 即,我认为:

    ExampleSingleton.Instance.SomeRequiredField
    

    更容易模拟,因为您需要替换/还原实例字段。关于“如何模拟静态这个或那个”的问题可能不时出现,可能是由于你发布的那个类:

    一般来说,C#中的单例模式可能不是最好的主意,因为它们通常更难模拟,除非你将构造函数设为public或使用ioc容器,但是如果你需要一个,那么实例getter可能更容易测试。

    第二点更多的是代码的增量维护成本。基本上要“添加到类”中,您必须更改两个代码点:

    class ExampleSingleton
    {
        ... existing code ...
    
        public static int ComputeComplicatedMethod()
        {
            return ComputeComplicatedMethodImplementation();
        }
    
        private int ComputeComplicatedMethodImplementation()
        {
            // really complex code.
        }
    }
    

    因此,您基本上为每个新字段添加了一个额外的抽象层,而对于一个get实例字段只需添加一次。或者你有一个使用内部静态单例的静态方法,如下所示:

    class ExampleSingleton
    {
        ... existing code ...
    
        public static int ComputeComplicatedMethod()
        {
            // use ExampleSingletonInstance here
        }
    }
    

    这真的没有比仅使用静态方法的静态类更好的了。一个更好的问题是为什么Singleton模式不仅仅用静态类实现?这可能会更好地解释:http://www.dotnetperls.com/singleton-static

答案 1 :(得分:1)

我认为你必须选择代码最少的解决方案(但看起来人们喜欢写一堆无用的代码,所以你可能很难解释你的意思。)

使用静态访问属性,例如在示例中保存一个单词:

string requiredField = ExampleSingleton.SomeRequiredStuff;

VS

string requiredField = ExampleSingleton.Instance.SomeRequiredStuff;

但是你必须为这个属性编写getter。

此外,如果你有很多属性,它就成了一个问题:你必须编写很多静态getter。

这不是标准并反对OOP精神:你处理一个对象的属性,所以得到对象然后属性。

此外,如果您的值是不变的,那么它不是属性!,习惯是将字段const和public放在一起。与ulong.MaxValue一样。

为方法执行此操作看起来不错。 (再次在OOP中,方法属于对象)。如果你不想要任何静态的东西,你将不得不构建调用非静态函数的静态函数。维护起来并不愉快。