views:

228

answers:

9

I was wondering, why do static Create methods exist?

For instance, why use this code:

System.Xml.XmlReader reader = System.Xml.XmlReader.Create(inputUri);

over this code:

System.Xml.XmlReader reader = new System.Xml.XmlReader(inputUri);

I cannot find the rationale for using one over the other, and can't find any relation between classes who use this construct over the other.

Can anyone shed some light on this?

+13  A: 

XmlReader is an abstract class. You cannot instantiate it.

Providing a Create method is an instance of the factory pattern. Depending on the specified arguments a different implementation of XmlReader is chosen and returned. For example, there are validating and non-validating XmlReader implementations in the .NET framework.

dtb
Never noticed the fact it's abstract. Is this true for every class having such a method?
GeReV
+1 but you could have spent a few more lines to give a little example..
Miky Dinescu
@GeReV: There are many abstract classes in the .NET framework that provide a Create method. But that's not a requirement. It's a design pattern.
dtb
+6  A: 

Because it can actually create and object of derived type that you have no access to or return an abstract class (as dtb answered). This is factory method pattern.

Andrew Bezzub
Well, if you actually read the wikipedia article you pasted you will notice that it describe a completely different pattern.
Grzenio
It is the same pattern. Depending on parameters passed to the method it creates objects of different types.
Andrew Bezzub
@Andrew Bezzub: Read again. The pattern you linked creates new instances depending on the actual implementation of an abstract Create method, not on the arguments passed to a single, common implementation. It's very similar though.
dtb
+1  A: 

This pattern allows the XmlReader class to provide you with instances of derived classes tailored to the parameters you passed to Create. Note in particular the overloads that accept an XmlReaderSettings object. A different XmlReader subclass can be returned to you depending on your settings.

A better example is WebRequest.Create(url). Depending on the URL you pass, you may receive an HttpWebRequest, an FtpWebRequest, etc.

John Saunders
+2  A: 
  • Because you don't have to commit to the exact class of object you get. Constructors can only construct objects from exactly one class.
  • Because you can give the method a meaningful name, e.g. BigInt.probablePrime(). Constructors can only have the same name as the class.
  • Because you can have more than one factory method for the same parameter type combination, e.g. Point.fromPolarCoords(int, int) and Point.fromCartesianCoords(int, int), but there can be only one constructor Point(int, int).

(A much more detailed answer is given in Bloch's 'Effective Java'.)

Kilian Foth
+1  A: 

Sometimes they exist as a form of self-documentation. I have a db access component that I can instantiate either with a connection string or the name of the connection in the config file. Both of these methods take strings as a parameter so they cannot be differentiated by arguments alone. So I created a FromConnectionString(string) factory method and a FromConnectionName(string) factory method. This nuance would entirely be lost by a new Foo(bool, string) line.

Robert Davis
+3  A: 

A more general answer...

The reason people like these kinds of methods, known as "static factory methods", is because you can give them a name (as opposed to constructors). So if you need three different constructors, you can instead create static factory methods which have names relevant to their use.

Another reason is that a factory method doesn't really need to create new objects - it can return the same one over and over if need be.

Zachary
+2  A: 

A constructor can only be used to create instances of one specific class, while a static Create method can create an instance of different classes depending on the input.

In the case of the XmlReader class the Create method will return an XmlDictionaryReader, XmlTextReader, XmlValidatingReader or XmlNodeReader, depending on which overload you use and what parameters you send to it.

Guffa
A: 

The idea is that this way they can change the implementation of XmlReader and not break any user code (e.g. they can change the actual type that is returned from the Create method).

I personally don't like this approach, because it creates an inverse relationship in the XmlReader class hierarchy. Maybe they thought that the Factory pattern is an overkill?

Grzenio
A: 

To encapsulate object creation.

Nick Miller