Thursday, 10 July 2014

Factory methods within a class can access private members.

There are times when I want to hide construction details and provide a factory method within the class to create objects.

I've found it handy for dependency injection, test classes, etc

Here's one of the patterns I've been using:

namespace Blog.Articles
  /// <summary>Use this class if you want a 'vanilla' implementation.</summary>
  public class ClassWithFactoryMethods : BaseClassWithFactoryMethods<ClassWithFactoryMethods>

  /// <summary>Demonstrate the implementation of a factory method which allows for sub-classing.</summary>
  /// <typeparam name="TSelf">The type of the class being. </typeparam>
  public class BaseClassWithFactoryMethods<TSelf> where TSelf : BaseClassWithFactoryMethods<TSelf>new()
    /// <summary>
    /// This the factory method which is responsible for creating objects of <typeparamref name="TSelf"/>.
    /// </summary>
    /// <param name="param">An example parameter.</param>
    /// <returns>Returns an object of the requested sub-type.</returns>
    public static TSelf CreateOne(string param)
      //// do some work before constructing the object using a private constructor

      //// ...

      // all the pre-requisites are satisfied so it's about time to construct ourselves one of these
      // using the public default contructor (which gives inheritors the change to do specialist work)
      var result = new TSelf();

      //// call any private initialisation methods

      // do some 'work'
      var otherParam = param.ToLower();

      // we can call private methods on this class in here where a 'normal' factory method could not

      return result;

    /// <summary>Show how the factory method can call the object's private methods.</summary>
    /// <param name="exampleParam">Example parameter.</param>
    private void Initialise(string exampleParam)
      // do some object initialisation

  //// Example of using the class with its internal factory and
  //// how to return sub-classes of it

  /// <summary>Show how to use these static methods.</summary>
  public static class TestClassWithFactoryMethods
    /// <summary>Show how to create objects using the factory method.</summary>
    public static void CreateOne()
      // create a 'standard' ClassWithFactoryMethods object 
      ClassWithFactoryMethods one = ClassWithFactoryMethods.CreateOne("Foo");

      // create another using the same method, but returning a derived object type
      MyClassWithFactoryMethods another = MyClassWithFactoryMethods.CreateOne("Foo");

      // we can now call methods on the sub-class

    /// <summary>Define a sub-class to show how the static method now returns the correct flavor of class.</summary>
    public class MyClassWithFactoryMethods : BaseClassWithFactoryMethods<MyClassWithFactoryMethods>
      /// <summary>Extend the base as required.</summary>
      public void ExtendedMethod()

No comments: