Reputation: 2015
I am currently enrolled in a CS2 course (data structures) where Java is the language used and I am interested in comparing and contrasting object instantiation using the traditional constructor method v.s. a factory method. Does one represent a greater degree of computing elegance than the other? Would a factory method handle parameters in a manner similar to a parameterized constructor? E.g:
public class Tester
{
private String name;
private int age;
// Parameterized constructor
public Tester(String myName, int myAge)
{
this.name = myName;
this.age = myAge;
}
}
Essentially, I'm very curious on how one would write an equivalent factory method and what the potential benefits would be of doing so.
Thanks,
~Caitlin
Upvotes: 3
Views: 2706
Reputation: 47729
A factory is useful in specific situations:
Where some reason such as the above is not present, there is no benefit to factory methods, and they simply obscure the logic.
There is no real restriction on what a factory can do, given that it can (if things are set up properly) access package level constructors and interfaces that are not accessible to the hoi polloi.
Added: To address the "inheritance" issue --
Let's say we have the classical Vehicle example, with Car and Truck subclasses. If you simply have CarFactory and TruckFactory then that increases the complexity of the code for no good reason (unless there are other compelling reasons for using factories).
But you can have a VehicleFactory and have it "decide", based on input or external factors, to create a Car or a Truck. This is a fairly common pattern.
However, if you were to (for some reason) have a VehicleFactory that only created Vehicle objects (not Cars or Trucks), and if use of the factory were mandatory (you couldn't access Vehicle's constructors), that would make it essentially impossible to subclass Vehicle. When you use a factory you make it very difficult (at the least) for someone else to add new subclasses.
Upvotes: 2
Reputation: 10084
According to the well-reasoned observations in Effective Java, the main advantages to static factory methods are as follows:
You can name them, unlike constructors which must always be named after the class. This makes code more readable and can avoid ugly situations where overloaded constructors might be impossible due to the types of arguments being the same, etc. In such a case, you could easily supply two factory methods with different names that indicate the difference.
A static factory method is not required to actually instaniate anything unlike a constructor which must create a new instance. Static factory methods are therefore essential for classes that are instance-controlled (eg. singleton classes).
Unlike constructors, a static factory method can return any object at all as long as the returned object matches or is a subclass of the return type. This enables interface-based type systems. The Enum framework of Java 1.5 makes use of this: the EnumSet class has no public constructors, only static factories. The actual object that is returned by the static factories varies depending on the size of the enum.
The main disadvantage of static factories is that they cannot be the basis of a class designed for inheritance. A class that provides only private constructors cannot be subclassed. A minor disadvantage of static factory methods is that they cannot be distinguished from other static methods, and so in order for them to be recognizable to the reader they usually follow naming patterns (they can be annotated if such a one is designed as a marker annotation for static factory methods).
Upvotes: 2
Reputation: 41281
Factory methods are nice as they can return a reference to an object that isn't necessarily an instance of that class. It can return that class, a subtype, or even null
, and generally carry themselves on any way they want that a method can. You can thus move logic of selecting types into your own code. You can return an existing instance where appropriate, saving heap space and such.
Another basic pseudoexample is Integer.forValue()
that can intern an integer, so identical immutable objects don't get recreated for no reason. Also see Executors.newXxxThreadPool()
.
A basic example:
public class Tester
{
private String name;
private int age;
// Parameterized constructor
private Tester(String myName, int myAge)
{
this.name = myName;
this.age = myAge;
}
public static Tester getTester(String mn, int ag){
if(age>0){return new Tester(mn, ag);}
else if(age>80){return new OldPersonThatExtendsTester(mn, ag);}
//we'd need a public or otherwise accessible constructor above. It's a subtype!
else {return null;} //yes, this is possible
}
}
Upvotes: 3