Welcome

My name is Jason and I am a software developer in the Bay Area. For fun I like to hike, run, shoot some photos, and take advantage of the many other activities California state has to offer. To the right you will see my resume.

Recent Books
  • Head First Design Patterns
    Head First Design Patterns
    by Elisabeth Freeman, Eric Freeman, Bert Bates, Kathy Sierra, Elisabeth Robson
Main | Quick Fix: File count of a directory »
Sunday
Sep012013

Using a Class Factory With Singletons

A singleton is an object that there is only 1 instance of. The way I learned how to pull this off was by making the constructor private and then having a static public method that would return the instance like so.

Code: C#

public class FooClass
{
  private static FooClass _fooClass = null;

  // Public static method
  public static FooClass GetInstance()
  {
    if (_fooClass == null)
      _fooClass = new FooClass();
    return _fooClass;
  }

  // Private constructor
  private FooClass()
  {
  }
}

But I was recently reading The Productive Programmer by Neal Ford and he discussed how this is no longer considered the best practice. The issue here is that a class should only be doing one thing. With the above pattern the class is doing two things; it's defining the behavior of FooClass and it's instantiating an instance of itself that it keeps track of. The second part is more commonly done with a class factory. So that's the current best practice. Define a singleton class with a private constructor and then create a class factory for it that handles the instance.

... But wait. The constructor is private? Yes. You'll use reflection to gain access to the constructor. I know this is not as easy, and depending on what you're doing you may still want to use the older method, but it's good to know, doesn't really add that much more code, and creates clear separation of functionality.

I went looking for examples of this in C# and didn't find any. So I threw the following example together for others that may be looking for the same. This isn't thread safe and any time I'm doing reflection I feel there should be try/catch logic surrounding it, but this is just a simple example to get you going.

public class FooClass
{
  private FooClass()
  {
  }
}

public static class FooClassFactory
{
  private static FooClass _fooClass = null;
  public static FooClass GetInstance()
  {
    if (_fooClass == null)
    {
      // Indicates that we're searching for a non-public instance constructor
      BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
      // Using null causes the DefaultBinder to be used
      Binder binder = null;
      // The types of the constructor's arguments, which there are none with this example
      Type[] argumentTypes = new Type[] {};
      // The DefaultBinder ignores the array of ParameterModifiers provided, so we'll just use null
      ParameterModifier[] parameterModifiers = null;

      Type fooClassType = typeof(FooClass);
      ConstructorInfo ctorInfo =
        fooClassType.GetConstructor(bindingFlags,
                                    binder,
                                    argumentTypes,
                                    parameterModifiers);
      _fooClass = (FooClass)ctorInfo.Invoke(new object[] {});
    }
    return _fooClass;
  }
}

The actual Type.GetConstructor() call could be done in a single line instead of all the setup I did with the BindingFlag, Binder, Type[], and ParameterModifier variables. I broke it down this way just to help understand what was happening.

I hope you found this useful. How would you change it to make it thread safe? Would you add a try/catch block? Leave a comment with your thoughts!

Reader Comments

There are no comments for this journal entry. To create a new comment, use the form below.

PostPost a New Comment

Enter your information below to add a new comment.

My response is on my own website »
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>