Factory Method Flashcards
Factory Method Pattern defined as
providing an interface for object creation but delegating the actual instantiation of objects to subclasses.
The problem with the next approach for object creation in Java:
SomeClass someClassObject = new SomeClass();
the code using the SomeClass’s object, suddenly now becomes dependent on the concrete implementation of SomeClass
tightly couples our code to the concrete implementation class, which is a violation of “code to an interface and not to an implementation”.
The class diagram consists of the following entities
Product
Concrete Product
Creator
Concrete Creator
The general setup is that the superclass has the implementation for all the methods other than the creation methods
. A create method is either abstract or comes with a default implementation and in turn is invoked by the other methods of the superclass.
The creation of the right objects is the responsibility of the subclasses.
. The pattern can be used whenever
a class doesn’t know ahead of time what subclass objects it would need to instantiate.
This is common problem in designing frameworks,
where the consumers of the framework are expected to extend framework provided abstract classes and hook-in functionality or object creations.
The Java API exposes several factory methods:
java.util.Calendar.getInstance()
java.util.ResourceBundle.getBundle()
java.text.NumberFormat.getInstance()
Caveats for Factory Method Pattern
The pattern can result in too many subclasse with very minor differences.
If the subclass extends the functionality, then the superclass can’t use it unless it downcasts it to the concrete type. The downcast may fail at runtime.
if we want to keep the creation of the F16 object parts within the same class and still be able to introduce new F16 variants as they come along, we could subclass F16 and delegate the creation of the right F16 variant object to the subclass handling that variant.
The method here is the makeF16() which we’ll make behave like a factory that produces the appropriate F16 variants.
public class F16 {
IEngine engine;
ICockpit cockpit;
protected F16 makeF16() {
engine = new F16Engine();
cockpit = new F16Cockpit();
return this;
}
public void taxi() {
System.out.println(“F16 is taxing on the runway !”);
}
public void fly() {
// Note here carefully, the superclass F16 doesn’t know
// what type of F-16 variant it was returned.
F16 f16 = makeF16();
f16.taxi();
System.out.println(“F16 is in the air !”);
}
}
public class F16A extends F16 {
@Override
public F16 makeF16() {
super.makeF16();
engine = new F16AEngine();
return this;
}
}
public class F16B extends F16 {
@Override
public F16 makeF16() {
super.makeF16();
engine = new F16BEngine();
return this;
}
}
A factory method may or may not provide a default or generic implementation but lets subclasses specialize or modify the product by overriding the create/make methods.
The client code can now use the newer models like so:
public class Client {
public void main() {
Collection<F16> myAirForce = new ArrayList<F16>();
F16 f16A = new F16A();
F16 f16B = new F16B();
myAirForce.add(f16A);
myAirForce.add(f16B);
for (F16 f16 : myAirForce) {
f16.fly();
}
}
}</F16></F16>