简体   繁体   中英

Which approach for kind of Singleton is better?

My program instantiates an object with parameters passed in command line. I need to be able to instantiate an object with those parameters but yet it should be created only once. I've read these posts 1 & 2 but I still didn't understand which approach is better:

1 - var myInstance = MyClass.Instance.Create("param1", "param2");

OR

2 - var myInstance = MyClass.Instance;
    myInstance.setParam1("param1");
    myInstance.setParam2("param2");

In the first approach the new instance for each different pair of parameters passed to Create will be created. The only way to prevent this is to set flag inside Create that will return the created instance.

In 2nd approach the problem is what if constructor of MyClass will depend on param1 and param2 ?

So, what would you suggest?

You can use the first approach too:

MyClass.Instance.Create("param1", "param2")

with slight difference, which may make parameters not mandatory, if you need, using Named Parameters , like say:

MyClass.Instance.Create(param1 = "param1", param2 = "param2")

So you can avoid using parameters at all (during call) and lay on default values provided in declaration.

I'd:

  • create an immutable Config class with a public constructor that takes the parameters
  • create a static method Config ParseCommandLine(string) that turns a command-line into a Config object.

    Since this is a pure function (no side-effects, no global state) it's easy to test this.

  • a static method Config ParseCommandLine() that gets the actual command line and calls the above method (a bit ugly, since it accesses global mutable state)
  • Finally use Config.SetInstance(ParseCommandLine()) to back the Instance property on your "singleton". This is a bit ugly, but using a singleton is ugly in the first place.

This "singleton" doesn't really enforce that there is a single config, but it's more of a default instance. In my experience real singletons are rarely needed, and even the default instance is kind of a hack.

You'd end up with something like this:

public class Config
{
    public string Param1{get;private set;}
    public int Param2(get;private set;}

    public Config(string param1, int param2)
    {
        Param1=param1;
        Param2=param2;
    }

    // take a string[] if you prefer to use Environment.GetCommandLineArgs
    public Config ParseCommandLine(string commandLine)
    {
        string param1=...;
        int param2=...;

        return new Config(param1:param1, param2:param2);
    }

    public Config ParseCommandLine()
    {
       return ParseCommandLine(Environment.CommandLine);
    }
}

I'd also consider throwing the static Instance property away, in favour of injecting the configuration to the objects that need it. But for a small program that may be over-engineering.

In your case it is better to use no Singleton.

Singleton's Intent:

  • Ensure that only one instance of a class is created.
  • Provide a global point of access to the object.

http://www.oodesign.com/singleton-pattern.html

Use a private static attribute as a flag if you need to ensure that only one instance is allowed.

Update:

public class MyClass {

    private static boolean isAlreadyInitiated = false;

    public MyClass() {
        if(isAlreadyInitiated){
            throw new IllegalStateException("Only one instance allowed.");
        }
        isAlreadyInitiated = true;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM