It's not Factory classes vs other classes, but Factory methods vs. using constructors. If you use a constructor to create an object, you must know its exact class. If you use a factory method to create one, then you only need to know a superclass or interface. For example, think about JDBC code. You work with objects that implement Connection and Statement and ResultSet interfaces, but you don't actually know the names of the concrete classes that are implementing them, because all the objects come from factory methods. This is good, because every JDBC driver has its own set of implementations of these interfaces. Because JDBC is set up with factory methods, you can write code which works with any driver -- the actual class names of the driver implementation classes are not hard-coded into your application.
Good answer! A lot of discussions on factory method and abstract factory don't emphasize that bit well enough. If you need to pick a class from column A, and you don't want to think too hard about it every time you do it, that's a hint that a factory would be handy. Push the decision making off to the factory. But how can it decide what to instantiate for you? The calling class might pass a parameter (I'm a printer, please give me something that can print) there might be a configuration file (we're using Oracle today, boys!) or a command-line option, or maybe the result of some other recent operation will give the factory a clue. I suppose in a simulation or game the factory might even choose a class at random!
A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
This little gem was actually what really turned my head about programming in Java. It took me a while to figure it out, though. It has to do with interfaces, and the phrase "programming to the interface". What does it mean? Well, start first with the concept of a variable of type MyInterface. Note that it's not MyClass, but MyInterface. Okay, now this variable can hold a reference to an object of any class that implements MyInterface, right? Okay, let's take a quick example. I have an interface called Light, with a method called on(), which turns on the light. Simple enough, right? So let's say for our example, we create a variable called myLight of type Light. Next we store in myLight a reference to an object of class IncandescentLight, which represents a standard light bulb. The myLight.on() method simply tells a current to flow into the bulb, turning on the light. A little later, there's a new type of Light called FluorescentLight. Its on() method has to do something a little special (what, I don't know, I'm not a lighting specialist, but let's say it needs to warm up the ballast or something). Now, the beauty of writing to the interface is that I can simply have my variable (myLight), which can contain either an IncandescentLight or a FluorescentLight. However, if I directly instantiate the light in my application code using some sort of switch statement, then every time I need to add a new type of light, I have to modify every piece of code that instantiates lights. We can avoid that by having a LightFactory class with a method createLight(), which returns a new object that implements Light. What class is it? We don't know and frankly we don't care. As long as the object honors the contract of the Light interface, then we can use it. And now, we can come up with a brand new light type such as NeonClass, and the only one who needs to know about the new class is the LightFactory. The LightFactory's createLight() method will determine which type of Light to instantiate and will return it to the caller. Now, you can also do this through subclassing - the factory method can return objects that are subclasses of a common class - but that can be a little less flexible that the interface technique. Man, that was a lot of words for a simple subject. Sorry about that! I hope I didn't just make things muddier. Joe