Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Factory vs instance constructors

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?

like image 449
Neil N Avatar asked Jun 02 '10 17:06

Neil N


People also ask

When would you use a factory constructor?

A factory constructor is a constructor that can be used when you don't necessarily want a constructor to create a new instance of your class. This might be useful if you hold instances of your class in memory and don't want to create a new one each time (or if the operation of creating an instance is costly).

What is the advantage of factory constructor?

The factory method is a smart way to create objects in Java and provides several advantages over the traditional approach of creating objects using constructors in Java. It can also improve the quality of code by making the code more readable, less coupled, and improves performance by caching.

What is an instance constructor?

An instance constructor is a method whose task is to create an instance of a class. A constructor is a member function whose task is to initialize the objects of its class, in other words it is a method of a class that executes when the class's objects are created.

Is a constructor a factory?

A constructor is concrete in that it creates objects as instances of a single class, and by a specified process (class instantiation), while a factory can create objects by instantiating various classes, or by using other allocation schemes such as an object pool.


3 Answers

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.

like image 111
Adam Robinson Avatar answered Oct 21 '22 03:10

Adam Robinson


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.

like image 21
Dan Diplo Avatar answered Oct 21 '22 03:10

Dan Diplo


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.
like image 10
nawfal Avatar answered Oct 21 '22 02:10

nawfal