views:

316

answers:

6

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?

+20  A: 

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
{
    ...
}

internal class Class2 : BaseClass
{
    ...
}

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

Adam Robinson
Technically, what he has is code that won't compile because his static Create method doesn't actually return anything. :)
Nathan Taylor
@Nathan: Yes, though I'm fairly certain that his code is an *example* rather than an actual code snippet (hence the `// some code...` blocks).
Adam Robinson
Adam, thanks for clearing this up, I had a sneaking suspicion calling it a static constructor was wrong. "Factory Pattern" is what I was looking for.
Neil N
@Adam Indeed, I'm just being somewhat cynical. :)
Nathan Taylor
+2  A: 

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.

Anders Abel
+2  A: 

The static Create method can instantiate and return:

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

Sometimes it is important to do bookkeeping and/or resource management for every instance of a class created. As a result, it is important that each construction is managed globally and a static method to do the construction will do that nicely.

plinth
As I pointed out in the question, this is something regular instance constructors could do as well.
Neil N
+1  A: 

As you can see, myClass is not following a "classic" factory pattern (where the class of the instance is not known/exposed outside the factory).

However in this case, the .NET framework team may not be aiming for a factory pattern, but I guess they do not want you to just new up the target class directly with a filename via a constructor. A factory might be overkill if only this class is being provided.

This pattern is sometimes seen in clone() methods, where an object can return an instance which is a kind of duplicate of itself.

Also maybe although the class is public, they might want to do some checks with the instantiation, filename, etc. and if they implemented a factory, the target class could still be created and invoked, bypassing the checks.

Ra
A: 

You can curry factory methods. Trying to curry a constructor gives you: a factory method.

I use this in some of my code that enumerates the Windows Device Manager tree. One of the classes lists the serial ports, each serial port has a connection factory property which returns a curried factory method with the port address (really ugly PNP device string) stored in internal state while the baud rate, stop bits, parity are all provided later.

Ben Voigt