0

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?

Community
  • 1
  • 1
theateist
  • 13,879
  • 17
  • 69
  • 109

3 Answers3

1

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.

Matías Fidemraizer
  • 63,804
  • 18
  • 124
  • 206
Tigran
  • 61,654
  • 8
  • 86
  • 123
  • But, wouldn't it be odd that someone will get always the same instance for whatever params he passes to `Create`? I mean is not it confusing? – theateist Feb 17 '13 at 17:01
  • It appears in intellisense in Visual Studio, and if you don't like deffault value, just specify the value you want, by passing it to a right parameter. – Tigran Feb 17 '13 at 17:03
  • if I call this 2 lines one right after other `MyClass.Instance.Create("param1", "param2"); MyClass.Instance.Create("param3", "param4");` should this throw exception if 2nd time trying to create or should it create new instance? – theateist Feb 18 '13 at 14:06
  • @theateist: calling *Create* (as a meaning of english word) I would expect thet it *creates* a new object. – Tigran Feb 18 '13 at 14:10
  • that's what I'm talking about. With this approach I cannot guarantee that the object will be created just one. I just need to rely on the user that he will know what he is doing, right? – theateist Feb 18 '13 at 20:43
  • @theateist: yes, correct. If you need only one instance, that filed with different values, based on some runtime condition, the second approach may be more readable, as first you create always the same object, after set its properties based on some conditions. – Tigran Feb 18 '13 at 21:15
0

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.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
  • But I want it to be accessible from any point in the code. That's why I want it to be something like singleton. Maybe term singleton is wrong here, but I hope you understood what I mean – theateist Feb 17 '13 at 21:55
  • @theateist 1) That's probably not good design 2) But if your rally want to, you can use a `Config.Instance` property for that, without enforcing the creating of a single instance. Essentially just a global variable of type `Config`. – CodesInChaos Feb 17 '13 at 21:58
  • I don't understand why it's not good design? Singleton usually instantiate itself using some config internally(e.g. app.config) or something like that. But, what if you need singleton and you don't have config file but get the initiation params from outside? Don't call it singleton, but why this cannot be happened? – theateist Feb 17 '13 at 22:09
  • I'll appreciate if you could answer my question – theateist Feb 18 '13 at 13:36
0

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;
    }
}
bancer
  • 7,475
  • 7
  • 39
  • 58