tags:

views:

1145

answers:

6

While modeling classes what is the preferred way of initializing it,

  1. Constructors
  2. Factory Methods

and what would be the considerations of using either of them.

In certain situations I prefer having a factory method which returns null if the object cannot be constructed. This makes the code neat. I can simply check if the returned value is not null or else take alternative action in contrast with throwing an exception from the constructor. (I personally don't like exceptions :( )

Edit:

Say, I have a constructor on a class which expects an id value. The constructor uses this value to populate the class from the database. In case a record with the specified id value does not exists the constructor throws a RecordNotFoundException. In this case I will have to enclose the construction of all such classes within a try..catch block.

In contrast to this I can have a static factory method on those classes which will return null if the record is not found.

Which approach is better in this case?

  1. Constructor
  2. Factory Method
+2  A: 

By default, constructors should be preferred, because they are simpler to understand and write. However, if you specifically need to decouple the construction niceties of an object from its semantic meaning as understood by the client code, you'd be better off using factories.

The difference between constructors and factories is analogous to, say, a variable and a pointer to a variable. There's another level of indirection, which is a disadvantage; but there's another level of flexibility too, which is an advantage. So while making a choice, you'd be well advised to do this cost versus benefit analysis.

Frederick
So, (TDD style) you would start with constructors as the simplest way of getting the job done. And then refactor to factories once you start getting code smells (like repeated conditional logic determining which constructor to call)?
AndyM
+17  A: 

From page 108 of Design Patterns: Elements of Reusable Object-Oriented Software by Gamma, Helm, Johnson, and Vlissides.

Use the Factory Method pattern when

  • a class can't anticipate the class of objects it must create
  • a class wants its subclasses to specify the objects it creates
  • classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate
Glenn
+2  A: 

Ask yourself what they are and why do we have them. They both are there to create instance of an object.

ElementarySchool school = new ElementarySchool();
ElementarySchool school = SchoolFactory.Construct(); // new ElementarySchool() inside

No difference so far. Now imagine that we have various school types and we want to switch from using ElementarySchool to HighSchool (which is derived from an ElementarySchool or implements the same interface ISchool as the ElementarySchool). The code change would be:

HighSchool school = new HighSchool();
HighSchool school = SchoolFactory.Construct(); // new HighSchool() inside

In case of an interface we would have:

ISchool school = new HighSchool();
ISchool school = SchoolFactory.Construct(); // new HighSchool() inside

Now if you have this code in multiple places you can see that using factory method might be pretty cheap because once you change the factory method you are done (if we use the second example with interfaces).

And this is the main difference and advantage. When you start dealing with a complex class hierarchies and you want to dynamically create an instance of a class from such a hierarchy you get the following code. Factory methods might then take a parameter that tells the method what concrete instance to instantiate. Let's say you have a MyStudent class and you need to instantiate corresponding ISchool object so that your student is a member of that school.

ISchool school = SchoolFactory.ConstructForStudent(myStudent);

Now you have one place in your app that contains business logic that determines what ISchool object to instantiate for different IStudent objects.

So - for simple classes (value objects, etc.) constructor is just fine (you don't want to overengineer your application) but for complex class hierarchies factory method is a preferred way.

This way you follow the first design principle from the gang of four book "Program to an interface, not an implementation".

David Pokluda
+1  A: 

Use a factory only when you need extra control with object creation, in a way that couldn't be done with constructors.

Factories have the possibility of caching for example.

An other way to use factories is in a scenario where you do not know the type you want to construct. Often you see this type of usage in plugin factory scenarios where each plugin must derive from a baseclass or implement some kind of interface. The factory creates instances of classes that derive from the baseclass or that implement theinterface.

Patrick Peters
+5  A: 

You need to read (if you have access to) Effective Java 2 Item 1: Consider static factory methods instead of constructors.

Static factory methods advantages:

  1. They have names.
  2. They are not required to create a new object each time they are invoked.
  3. They can return an object of any subtype of their return type.
  4. They reduce verbosity of creating parameterized type instances.

Static factory methods disadvantages:

  1. When providing only static factory methods, classes without public or protected constructors cannot be subclassed.
  2. They are not readily distinguishable from other static methods
cherouvim
This seems to me rather a severe bug in Java, then a general OOD problem. There are numerous OO languages that don't even *have* constructors, yet subclassing works just fine.
Jörg W Mittag
+1  A: 

A concrete example from a CAD/CAM application.

A cutting path would be made by using a constructor. It is a series of lines and arcs defining a path to cut. While the series of lines and arcs can be different and have different coordinates it easily handled by passing a list into a constructor.

A shape would be would be made by using a factory. Because while there is a shape class each shape would be setup differently depending on what type of shape it is. We don't know what shape we are going to be initializing until the user makes a selection.

RS Conley