Up to now, I identified three different kinds of factory patterns, which are similar to each other.
Simple, but powerful: The Simple Factory
The simple factory in Java is implemented as a static method, which returns a object of a certain type. This object can be newly created or a singleton (in contrast to object creation with constructors, which create new objects always).
Advantages [taken from Effective Java (2nd Edition)]
- Factory methods have names
- Factory methods decide what kind of objects are created
- Factory methods can return objects of any subtype
- Verbosity of creating parameterized type instances is reduced
Constructors differ only by signature. With factory methods, the method itself can describe the kind of object created.
With factory methods, newly created objects can be returned as well as singletons.
Depending on the submitted arguments, the method can decide to return subtypes of the return type (see example below).
Redundant specification of the form Map map = new HashMap() is not necessary with factory methods, since the compiler is able to infer the type by type inference.
Disadvantages:
- Factory methods do not favor inheritance
- Factory methods cannot be identified as creational methods as easy as constructors
Returned (non-public) types of factory methods cannot be subclasses (if they have no public or protected constructors).
This can be leveled by using conventions, eg. valueOf, getInstance, of depending on the context.
public class Factory {
public static Item createItem( Object decideUpon ) {
int itemType = figureOutItemType( decideUpon );
switch( itemType ) {
case Constants.Type1:
return new Type1();
case Constants.Type2:
return new Type2();
// etc.
}
}
}
And now in Scala:
object Factory {
def createItem( decideUpon:String ):Item = decideUpon match {
case "type1" => new Item1Type
case "type2" => new Item2Type
case _ => error("Unknown option.")
}
}
The real Factory Method
The Factory Method is used to create several concrete objects of one abstract class.
In contrast to the Simple Factory described above, the factory itself is subclassed, therefore a concrete factory which creates concrete classes can be created depending on the context.
public abstract class Factory {
public abstract Item createItem();
}
public class Item1Factory extends Factory {
public Item createItem() {
return new Type1();
}
}
public class Item2Factory extends Factory {
public Item createItem() {
return new Type2();
}
}
In Scala, the code is almost the same, is might just be simplyfied by the use of pattern matching (not equal to the Java version).
trait Factory {
def create( decideUpon:String ): Item
}
object Item1Factory extends Factory {
def create(): Item = instanceType match {
case "type1" => new Type1Item
case _ => error("Unknown option.")
}
}
Last, not least: Abstract Factory
In short, an Abstract Factory is used to create families of related objects.
The creation methods inside the Abstract Factories are usually implemented as Factory Methods.