Vaccano
Vaccano

Reputation: 82341

A more compact way to do a singleton with a parameter

I am not really that good at patterns. (But I do realize that they are very important.) I have a scenario that needs a singleton but also needs to take a parameter. Normally for a singleton I just make a static method that does a:

return _instance ?? (_instance = new SingletonClass()); 

But when a parameter is involved you either have to pass the parameter every time to access things (just in case that is the time you are going to be doing the constructing) or do something like I did here:

public class PublicFacingSingleton
{
    private readonly string _paramForSingleton;
    public PublicFacingSingleton(string paramForSingleton)
    {
        _paramForSingleton = paramForSingleton;
    }

    private PrivateFacingSingleton _access;
    public PrivateFacingSingleton Access
    {
        get 
        { 
            // If null then make one, else return the one we have.
            return _access ?? 
                   (_access = new PrivateFacingSingleton(_paramForSingleton)); 
        }
    }
}

public class PrivateFacingSingleton
{
    private readonly ClassWithOnlyOneInstance _singleInstance;
    public PrivateFacingSingleton(string paramForSingleton)
    {
        _singleInstance = new ClassWithOnlyOneInstance(paramForSingleton);
    }

    public WorkItem ActualMethodToDoWork()
    {
        return _singleInstance.UseTheClass();
    }
}

and then create the PublicFacingSigleton and use that. For example:

var publicFacingSingleton = new PublicFacingSingleton("MyParameter")
publicFacingSingleton.Access.ActualMethodToDoWork();

There are several problems with this. A few of them are:

  1. I have two classes now instead of one
  2. An unknowing developer could still easily create a PrivateFacingSingleton instance.

Is there a better way that addresses my concerns but does not have me passing in a param every time I want to call ActualMethodToDoWork() (ie publicFacingSingleton.Access("MyParameter").ActualMethodToDoWork())

NOTE: The above code is an example taken from my actual code. If you want to see my actual code it is here.

Upvotes: 3

Views: 463

Answers (2)

Whimsical
Whimsical

Reputation: 6355

Maybe a combination of singleton and factory pattern would suit your needs?

Multiple functions can be placed within your singleton class, which are instantiated only once. Meanwhile, the singleton class acts as a factory giving out the required output and also acting as an abstraction to the creation logic.

public class Singleton {

    private static final Singleton INSTANCE = new Singleton();
    private Object FactoryOutput;

    // Private constructor prevents instantiation from other classes
    private Singleton() { }

    public static Singleton getInstance() {
        return INSTANCE;
    }

    public Object SomeClassWhichNeedsSingleInstantiation(Object Parameter)
    {
        If(FactoryOutput == null)
        {
            FactoryOutput = new FactoryOutput(Parameter);
        }
        return FactoryOutput;
    }
}

Upvotes: 1

Emond
Emond

Reputation: 50672

This might be considered as not a solution but I do think it should be mentioned here:

When a singleton needs a parameter it probably is not a singleton.

Chances are that you will need an instance that was created with an other value for the parameter (now or in the long run)

Upvotes: 2

Related Questions