Factory vs instance constructors

18,268

Solution 1

Note: What you have is not a static constructor, it's a static function that creates the instance rather than calling the instance constructor yourself. A static constructor is a different thing entirely.

The factory pattern is a classic example of using a function (static or not) to instantiate a type rather than using the constructor directly. Note that the actual instance constructor will get called no matter what, but the static function provides a layer of indirection that allows it to return an instance of any type that either is or inherits from the return type, rather than only instances that are the return type.

For example:

public abstract class BaseClass
{
    public static BaseClass Create(int parameter)
    {
        if (parameter == 1)
        {
            return new Class1();
        }
        else
        {
            return new Class2();
        }
    }
}

internal class Class1 : BaseClass
{
    //code here ...
}

internal class Class2 : BaseClass
{
    //code here ...
}

This allows you to hide Class1 and Class2 from external assemblies while still allowing the consumer to deal with something specialized.

Solution 2

I was researching this very point and came across this question but didn't feel it had been answered fully. However, I did find this handy article - Design Guidelines Update: Factories vs. Constructors - by Krzysztof Cwalina (a a Principal Architect on the .NET Framework). It is worth reading the entire article, but here is a brief summary of the main points:

The most common and consistent way to create an instance of a type is via its constructor. However, sometimes a preferable alternative is to use the Factory pattern.

Do prefer constructors over Factories as they are generally more consistent and convenient than specialized construction mechanisms.

Do implement Factory operations as methods, not properties.

Do return instances as method return values, not as out parameters.

Consider using a Factory if you need more control over the creation patterns of instances.

Consider naming Factory methods by concatenating “Create” and the name of the type being created.

Consider naming Factory types by concatenating the name of type being created and “Factory.”

Do not implement your Factory using a static method if the construction operation must be available for subclasses to specialize.

Do use a Factory for conversion style operations.

Do use a Factory if an operation requires parameter information which feels unnatural to pass to a constructor.

Do not use a Factory in situations where the creation operation will be used as a core scenario for instantiation of a type. In these situations, discoverability and consistency are paramount.

Consider using a constructor instead of a Factory. Only after this thought process should you proceed with the implementation of a Factory.

Factories are also often handy to enable type specialization through polymorphism.

Do use a Factory if API users will be coding to a base class or interface whose implementation is subject to change over time.

Do use Factory methods in cases where a developer might not know which type to construct, for instance when coding against a base type or interface.

Do implement Factory operations as virtual instance methods rather than static if they must support polymorphic extension.

Do use the Singleton pattern for Factories which are instance based so as not to force developers to instantiate a Factory type just to invoke one of its members.

Do use a Factory method if a constructor would be insufficient to describe the operation being performed, and the additional information gained from an individually named Factory makes an operation’s purpose clearer.

Solution 3

Another common case where factory methods help (in languages like C# which don't support type inference from constructor) is when you have to minimize type parameter specification. Consider the common case of Tuple class. You can either do:

new Tuple<int, int>(1, 1); //constructor call

or

Tuple.Create(1, 1); //factory pattern.

Solution 4

The static Create method can instantiate and return:

  • A MyClass instance
  • An instance of any subclass of MyClass
  • null

Solution 5

The factory method is often used to hide the exact type of the object being created. An abstract class can have a static factory method, which then selects the concrete derived class to instantiate depending on some condition. Only the abstract base class is publicly documented. This leaves the library supplier some freedom to change the exact type being instantiated without breaking existing code.

An example from the .NET framework is the static factory methods on the Expression class.

Share:
18,268
Neil N
Author by

Neil N

Boom.

Updated on June 06, 2022

Comments

  • Neil N
    Neil N almost 2 years

    I can't think of any reasons why one is better than the other. Compare these two implementations:

    public class MyClass
    {
        public MyClass(string fileName)
        {
            // some code...
        }
    }
    

    as opposed to:

    public class MyClass
    {
        private MyClass(){}
    
        public static MyClass Create(string fileName)
        {
           // some code...
        }
    }
    

    There are some places in the .Net framework that use a static method to create instances. At first I was thinking, it registers it's instances to keep track of them, but regular constructors could do the same thing through the use of private static variables.

    What is the reasoning behind this style?

  • Nathan Taylor
    Nathan Taylor almost 14 years
    Technically, what he has is code that won't compile because his static Create method doesn't actually return anything. :)
  • Adam Robinson
    Adam Robinson almost 14 years
    @Nathan: Yes, though I'm fairly certain that his code is an example rather than an actual code snippet (hence the // some code... blocks).
  • Neil N
    Neil N almost 14 years
    As I pointed out in the question, this is something regular instance constructors could do as well.
  • Nathan Taylor
    Nathan Taylor almost 14 years
    Indeed, I'm just being somewhat cynical. :)
  • supercat
    supercat almost 13 years
    Slight addendum: in either of the first two cases, the object returned may be a newly-created object instance or a shared object instance. The distinction may be important if other code checks for reference equality.
  • Icemanind
    Icemanind over 9 years
    @AdamRobinson - You said The factory pattern is a classic example of using a function (static or not) to instantiate a type. Wouldn't it have to be static? Because if it had no constructors, how could you call any methods?
  • Adam Robinson
    Adam Robinson over 9 years
    @icemanind: Something like DataTable.NewRow comes to mind. In the scenario where you're working with typed DataSets, each table has two types: a type that inherits from DataTable and a type that inherits from DataRow (to provide strongly-typed properties to read/write against the loosely-typed backing store of the table). The table type would override NewRowFromBuilder to instantiate the inherited row type and return it. Calling NewRow on the table then trickles down to this and you have the table instantiating the row for you (via instance method) rather than using the constructor
  • Icemanind
    Icemanind over 9 years
    @AdamRobinson - Thanks for the clarification. I see what you mean now. It seems like a very limited scenario though, but I do understand.
  • Adam Robinson
    Adam Robinson over 9 years
    Yeah, if you're suggesting that most factory implementations involve a static function doing the constructing, then I'd wager you're right.
  • sc911
    sc911 over 2 years