Factory vs instance constructors

I can not think of any reason why one is better than the other. Compare these two implementations:

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

Unlike:

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

There are several places in the .NET framework that use the static method to instantiate. At first I thought it would register instances to keep track of them, but regular constructors could do the same with private static variables.

What is the reason for this style?

+30
constructor c # oop coding-style
source share
10 answers

Note. What you have is not a static constructor, it is a static function that creates an instance instead of calling the instance constructor. The static constructor is completely different.

The factory pattern is a classic example of using a function (static or not) to create an instance of a type, rather than using the constructor directly. Note that the actual instance constructor will be called no matter what, but the static function provides an indirect layer that allows it to return an instance of any type that is either or inherits from the return type, not just the 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 at the same time allowing the consumer to deal with something specialized.

+44
source share

I studied this moment and came across this question, but did not feel that it was fully answered. Nevertheless, I found this convenient article - Updating design rules: factories and designers - Krzysztof Kvalina (chief architect on the .NET Framework), It is worth reading the whole article, but here is a brief overview of the main points:

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

Prefer designers over factories, because they are usually more consistent and convenient than specialized construction mechanisms.

Perform Factory operations as methods, not properties.

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

Consider using Factory if you need more control over instance creation.

Consider the names of Factory methods by combining "Create" and the name of the type being created.

Consider Factory type names by concatenating the type name, which is and

Do not use your Factory using the static method if the construction operation should be available for specialized subclasses.

Use Factory for conversion style operations.

Use Factory if the operation requires parameter information that seems unnatural to pass to the constructor.

Do not use Factory in situations where the create operation is used as the main script to create an instance of the type. In these situations, openness and coherence are paramount.

Consider using a constructor instead of Factory. Only after that you should start implementation of Factory.

Plants can also often be useful for incorporating type specialization through polymorphism.

Use Factory if API users will encode a base class or interface whose implementation may change over time.

Use Factory methods in cases where the developer may not know what type to build, for example, when encoding with a base type or interface.

Use Factory operations as virtual instance methods than static methods if they must support polymorphic expansion.

Use the Singleton pattern for instance-based factories since this does not force developers to create an instance of type Factory only to call one of its members.

Use the Factory method if the constructor is insufficient to describe the operation being performed and additional information received from the individually named Factory, the operation is clearer.

+16
source share

The static Create method can create and return:

  • A MyClass instance
  • An instance of any subclass of MyClass
  • null
+7
source share

Another common case where factory methods help (in languages ​​like C # that do not support type inference from the constructor ) is when you need to minimize the specification of a type parameter. Consider the general case of the Tuple class. You can:

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

or

 Tuple.Create(1, 1); //factory pattern. 
+7
source share

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

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

+3
source share

Sometimes it is important to keep accounting and / or resource management for each instance of the created class. As a result, it is important that each construction is controlled globally, and the static construction method will do it beautifully.

+1
source share

As you can see, myClass does not follow the “classic” factory pattern (where the instance class is unknown / open outside the factory).

However, in this case, the .NET framework team may not aim for the factory pattern, but I think they don’t want you to simply update the target class directly using the file name through the constructor. A factory may be redundant if only this class is provided.

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

Perhaps, although the class is publicly available, they may want to perform some checks using the instance, file name, etc., and if they implemented a factory, the target class could still be created and called, bypassing the checks.

+1
source share

The methods that make you design are very useful for:

 public class Class { public static List<Class> FromFiles(IEnumerable<String> paths) { List<Class> instances = new List<Class>(); foreach (string path in paths) { instances.Add(new Class() { Path = path }); } return instances; } public string Path { get; set; } } 

... since the "normal" constructors cannot do this.

+1
source share

You can use factory methods. Curry's attempt to build a constructor gives you: factory method.

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

0
source share

Failure to comply with assembly requirements that reference your assembly is another reason.
It seems that if you call the constructor for the class in another assembly, your assembly will be needed to reference all assemblies that define any of the types used by any overload. You can get around this forced dependency using different factory methods.

Example:

Assembly1.dll (does not require a reference to BarAssembly.dll)
class Class1 { void Main(){ var foo = new Foo(); } }

Assembly2.dll (there is no need to refer to BarAssembly.dll, because CreateFoo and CreateFooWithBar are not overloads)
class Class2 { void Main(){ var foo = CreateFoo(); } }

FooAssembly.dll (link to BarAssembly.dll required)
class Foo { public CreateFoo(){ ... } public CreateFooWithBar(Bar bar){ ... } public Foo(){ ... } public Foo(Bar bar){ ... } }

BarAssembly.dll
class Bar { public Bar(){ ... } }

Note: Complied in VS2013 building vs .NET Framework 4.5

0
source share

All Articles