I’ve always wondered why designers of some classes furnish a static Create method instead of a constructor.
public class MyClass
{
// Static Create method.
static MyClass Create()
{
return new MyClass();
}
// Private constructor.
private MyClass()
{
// Construct the object.
}
}
During a recent experience with the Entity Framework 4.1, I saw the power of that pattern. It shows us the first reason to use Create.
Reason 1: Transparently deliver a subclass.
One of the jobs of the Framework is to create “entities.” (An entity usually corresponds to a record in a database table.) You can use the entity class’ constructor and get a POCO (Plain Old CLR Object), or you can use DbSet<TEntity>.Create* to potentially get a derived, proxy object that has extra features. The consuming code enjoys the simplicity of the POCO, but the POCO has superpowers.
So that is the first reason to use the Create pattern: you can transparently deliver a subclass that has extra features (being careful to obey the Liskov Substitution Principle, of course!).
Reason 2: Force consumers to program to an interface.
Another use of Create is to ensure that consumers of your class only consume the class’ interface, thus decoupling your class from their code. To really lock things down, make the constructor private or protected.
public interface IFoo
{
int Bar { get; set; }
}
public class Foo : IFoo
{
public int Bar { get { return 1; } }
public IFoo Create()
{
return new Foo();
}
private Foo()
{
// Construct the object
}
}
Reason 3: Allow or force consumers to program to an abstract base class.
You can take that one step further by putting your Create method in an abstract base class. XmlWriter.Create exemplifies this technique. Consumers must program to the abstract type, decoupling them from the specific implementations. (This is a specific application of the first reason
There are also reasons not to use Create. Your Inversion of Control container will not work with it, for example. But it’s definitely one more tool you'll want in your toolbox.
* - DbSet<TEntity>.Create is not a static member of the TEntity class, but an instance member of the type of DbSet that will contain the entity. The principle of using a Create method rather than a constructor is the same, however.