-1

I have been reviewing some code of some old projects and I found a singleton there. It is a requirement to use a singleton and I was thinking of a way to make it look "simpler" when using.

I found, it would be easier to access the methods and properties like a static class. So I basically implemented a singleton using static methods to skip the requirement to use GetInstance(). This is how I implemented it:

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

So when you want to access the singleton values you can just do it like this:

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

Am I violating the principles of the singleton pattern here? It basically is still a singleton pattern but the work of getting the instance is done internally. What could be the con's of this example? Are there other pro's?

Thanks

El Mac
  • 3,256
  • 7
  • 38
  • 58
  • Good question. Can't wait to see people come here and put it on fire because it's subjective.. – Orace Mar 30 '15 at 09:37
  • @Orace I believe, if I ask what could go wrong with this approach, it is not subjective anymore? – El Mac Mar 30 '15 at 09:40
  • I will not give arguments to kill your question :o) – Orace Mar 30 '15 at 09:53
  • If you want to save some typing you could just do something like this: private SingletonExample singletonExample = SingletonExample.Instance; anywhere you need access to your Singleton and then call its properties via singletonExample.SomeRequiredField; Not a common practice but a possibility. – Paul Weiland Mar 30 '15 at 10:31

2 Answers2

3

In terms of cons, there are two that have bitten me in the past:

  1. It's hard to mock the singleton due to the fact that the getters are static
  2. Changes to the singleton interface need 2 separate changes (one for the public static, one for the internals).

Namely, I think that this:

ExampleSingleton.Instance.SomeRequiredField

Is easier to mock simply because you would need to replace/revert the Instance field. Questions pop up from time to time around "how to mock static this or that" probably due to classes like the one you posted:

In general, a singleton pattern in C# is probably not the best idea due to the fact that they are harder to mock in general, unless you make the constructor public or use a ioc container, but if you need one, having the instance getter is probably easier to test in general.

Second point is more around incremental maintenance cost of code. Basically to "add to the class" you have two points of code that must be changed:

class ExampleSingleton
{
    ... existing code ...

    public static int ComputeComplicatedMethod()
    {
        return ComputeComplicatedMethodImplementation();
    }

    private int ComputeComplicatedMethodImplementation()
    {
        // really complex code.
    }
}

So you've essentially added an extra layer of abstraction for every new field versus just once for a get instance field. Either that or you have a static method that uses the internal static singleton like so:

class ExampleSingleton
{
    ... existing code ...

    public static int ComputeComplicatedMethod()
    {
        // use ExampleSingletonInstance here
    }
}

Which is really no better than just having a static class with static methods. A better question is why isn't the Singleton pattern implemented with just a static class? That might be better explained here: http://www.dotnetperls.com/singleton-static

Community
  • 1
  • 1
Jun
  • 764
  • 5
  • 8
1

I think you have to choose the solution with the least code (but it looks like people likes to wrote a bunch of useless code, so you may have difficulty to explain what is your point).

Use a static access to a property like in your example save you a word:

string requiredField = ExampleSingleton.SomeRequiredStuff;

vs

string requiredField = ExampleSingleton.Instance.SomeRequiredStuff;

But you have to wrote the getter for this property.

Also if you have a lot of properties it became an issue: you have to wrote a lot of static getter.

And this is not standard and go against OOP spirit: you handle the property of an object, so get the object then the property.

Also if your value is invariable, it is not a property!, the habit is to put the field const and public. Like ulong.MaxValue.

Doing this for the methods look like a bad idea. (and again in OOP, method belong to objects). If you don't want to have anything static you will have to build static functions that call the non-static ones. It will be not pleasant to maintain.

Orace
  • 7,822
  • 30
  • 45
  • So basically it is not an OOP approach. Initially it would cause to write less code, but if the singleton gets more complex it will get hard to mantain with more code than a standard approach. – El Mac Mar 30 '15 at 10:22