Factory Pattern in C#: How to Ensure an Object Instance Can Only Be Created by a Factory Class

Factory pattern in C#: How to ensure an object instance can only be created by a factory class?

Looks like you just want to run some business logic before creating the object - so why dont you just create a static method inside the "BusinessClass" that does all the dirty "myProperty" checking work, and make the constructor private?

public BusinessClass
{
public string MyProperty { get; private set; }

private BusinessClass()
{
}

private BusinessClass(string myProperty)
{
MyProperty = myProperty;
}

public static BusinessClass CreateObject(string myProperty)
{
// Perform some check on myProperty

if (/* all ok */)
return new BusinessClass(myProperty);

return null;
}
}

Calling it would be pretty straightforward:

BusinessClass objBusiness = BusinessClass.CreateObject(someProperty);

make sure object only created by factory (C#)

If, for some reason, you need the factory and the constructed class to be in separate assemblies (which means simply using internal won't work), and you can ensure that your factory gets a chance to run first, you can do this:

// In factory assembly:

public class Factory
{
public Factory()
{
token = new object();
MyClass.StoreCreateToken(token);
}

public MyClass Create()
{
return new MyClass(token);
}

private object token;
}

// In other assembly:

public class MyClass
{
public static void StoreCreateToken(object token)
{
if (token != null) throw new InvalidOperationException(
"Only one factory can create MyClass.");

this.token = token;
}

public MyClass(object token)
{
if (this.token != token) throw new InvalidOperationException(
"Need an appropriate token to create MyClass.");
}

private static object token;
}

Yes, it's cumbersome and awkward. But there may be weird situations where this is actually a good solution.

Benefits of a Factory for model instantiation without need for creation logic

Two benefits, one somewhat abstract and one practical.

  1. Object instantiation is a separate responsibility. Under SRP, your business logic code should not be doing it. The responsibility of object creation belongs to the composition root and to factories.

  2. If your code uses new there is more or less no way to substitute another class for unit testing. If your code uses an IXXXFactory of some kind, your unit test code can supply its own factory which would return mock or stub objects, allowing you to isolate the class under test. This makes unit testing much easier.

Forcing the use of a factory object to instantiate a class

Some options:

  • reflection
  • register delegate that creates the class with factory class
  • configure your DI container to behave the way you need for that type of classes

Approximate code for delegate approach:

public class Factory {
private static Dictionary<Type, Func<Model>> creators;
public void AddCreator<T>(Func<T> creator) where T:Model
{
creators.Add(typeof(T), ()=> creator());
}

public static T Instance() where T : Model
{
return (T)(creators[typeof(T)] ());
}
}

Relationship between factory design pattern and polymorphism

You use the factory pattern if you want to be able to change the concrete type that is created later on - in other words to use polymorphism to return an instance of a derived class in the form of the base class.

So polymorphism is a precondition for the factory pattern to work. Without polymorphism, you couldn't return an instance of a derived class in the form of the base class.



Related Topics



Leave a reply



Submit