If not a singleton, then what?

So I am working on the middle layer.

I am consuming a COM DLL that deals with low-level hardware interop and provides a UI for IO input with the hardware.

As part of my layer's design, we put in a context manager that organizes various hardware to create contexts that our application can work with.

So I want to ensure that the developer who is working with my code has one context manager to work with, and then within that context manager, I can ensure that we only allocate one work queue per hardware device.

Just to complicate this, there is some initialization that needs to be done before I can start adding to hardware devices. Something that would be simple if it weren't for the fact that you usually only access singleton via the readonly property.

I know the singleton pattern can complicate many because of its global availability. I really do not want and do not need this class to have a globally singleton accessibility, I just want to ensure that only one is created inside the application.

For this I would be crazy to do something like this to basically give my singleton a constructor:

public class MySingleton
{
 private static MySingleton _MySingleton;
 private static object singletonLock = new object();

 private MySingleton(int foo1, string foo2)
 {
  //do init stuff
 }

 public static MySingleton StartSingleton(int foo1, string foo2)
 {
  try
  {
   Monitor.Enter(singletonLock);
   if (_MySingleton == null)
   {
    _MySingleton = new MySingleton(foo1, foo2);
   }
   else
    throw new Exception("Singleton already initialized");
  }
  finally
  {
   Monitor.Exit(singletonLock);
  }
  return _MySingleton;
 }

 public static MySingleton Instance
 {
  get
  {
   try
   {
    Monitor.Enter(singletonLock);
    if (_MySingleton == null)
    {
     throw new Exception("Singleton must be Initialized");
    }
   }
   finally
   {
    Monitor.Exit(singletonLock);
   }
   return _MySingleton;
  }
 }
}

      

+2


source to share


3 answers


It's not crazy code, but it doesn't matter. If you remove the property Instance

, then it will no longer be a singlet.

Global availability isn't all that makes singles nasty. What makes them nasty is that they are used across the entire system directly if you can't keep track of all these usages. This is why it is such a nightmare in multi-threaded code, which is why it is so difficult to unit test anything with single elements inside.



So, if this is your code, I would recommend that you only create one object during application initialization and pass it using dependency injection or as a simple constructor argument. If it's a library, you can either check the constructor if it's created or not, or throw an exception, or you can go with a static constructor like you did, but without a property Instance

, forcing developers to loop through the instance.

As always, you can just create a singleton, because all that matters is that the product works and customers use it, singles or no singlets doesn't matter much.

+4


source


You wouldn't be crazy. The singleton avoids the disadvantages of globals in that they fit into names. Although it is available globally through a static function call, it is not a global variable. And furthermore, it is accessed through a namespace so no one can put it in a global var called temp and then assign something else to temp. They should always get a local reference to it by doing

MySingleton singletonRef = MySingleton.Instance ();



when their scope is closed, this link dies and therefore it is not a global variable.

+1


source


So if I just need you to be able to create only one version of my object, then something like this will work:

public class MySingleton
{
    private static int objectCount = 0;
    private static object singletonLock = new object();

    public MySingleton(int foo1, string foo2)
    {
        try{
            Monitor.Enter(singletonLock);
            if (objectCount != 0)
            {
                throw new Exception("MySingleton Already exsists");
            }
            else
            {
                objectCount++;
            }
        }
        finally{
            Monitor.Exit(singletonLock);
        }

        //do initialization stuff

    }
}

      

clearly not a real singleton anymore.

0


source







All Articles