Reputation: 121
I'm using GoF design patterns since a while and I found that I misunderstood some of them.
I'm focused on Factory (not Abstract Factory). Until now, I've thought Factory was a class with several creational methods like BorderFactory in Java API:
All methods returning the same kind of abstraction (e.g. interface).
However, I've found that "Factory" in GoF (real name "Factory Method") is not really this kind of class, but a class with a unique method returning a concrete type depending on the input parameter (e.g. a string). I'm using this kind of factory for parsing purposes (modeling language).
GoF creational patterns are Factory Method, Abstract Factory, Builder, Singleton and Prototype. There is no "Factory", unless Factory is considered as a refined Factory Method (too many input parameters -> need to define several createXXX methods) ?
What do you think about this ?
Thanks.
Upvotes: 0
Views: 739
Reputation: 865
You've stumbled upon exactly the situation that was described by GoF book authors 15 years after releasing the book: http://www.informit.com/articles/article.aspx?p=1404056 Just read thoroughly -
Factory Method would be generalized to Factory
My best suggestion to people is not to remember the canonical shape of GoF pattern or its implementation but rather to remember the idea behind the pattern. The idea of that generalized Factory pattern would be to provide a method that is not a direct class' constructor and will return instances of its subclasses - either as interface references (preferred) or subclass instances. Indeed in modern languages the 'canonical' shape/implementation of GoF patterns doesn't make much sense frequently, but the idea behind each pattern totally makes sense as always - apply only when needed though.
Upvotes: 1
Reputation: 131346
In OOP, static factories are indeed not known as GOF design patterns.
These are methods that allow to create and return objects.
These has broad intentions such as :
Note also that a static
factory may not do any of these and just be used as a helper method to create objects. So it may use no OOP features at all, w
which is not the case of factory method and of GOF design pattern in general.
There is no "Factory", unless Factory is considered as a refined Factory Method (too many input parameters -> need to define several createXXX methods) ?
IHMO a factory method looks like more a variant of the static factory.
It doesn't have the same intention and is much more specialized : it doesn't abstract/hide the object creations but delegates it to some factory subclasses.
Note also that the factory method can also rely on static factories to create their objects while the reverse is less obvious.
So I consider this creational GOF pattern as more structuring than a static
factory.
Example to illustrate :
An Animal
can have children. We have several subclass of Animal
and only Animal
subclasses should know which instance return for their children.
Here we want to use a factory method as we let the instantiation task to subclasses.
You could so do :
public abstract class Animal {
public abstract ChildAnimal createChild(String name, LocalDate birthdate);
}
public class Dog extends Animal {
@Override
public ChildAnimal createChild(String name, LocalDate birthdate) {
return new LittleDog(name, birthdate);
}
}
public class Cat extends Animal {
@Override
public ChildAnimal createChild(String name, LocalDate birthdate) {
return new LittleCat(name, birthdate);
}
}
And so for...
Ok, now suppose that LittleCat
happens to have multiple constructors.
It doesn't make the API simple.
Here we could use factory static methods instead of constructors to make things clearer :
public class LittleCat implements ChildAnimal {
static LittleCat withNameAndBirthDateAndParents(String name, LocalDate birthdate, Cat dad, Cat mom) {
return new LittleCat("kitty", birthdate, dad, mom);
}
static LittleCat withNameAndBirthDate(String name, LocalDate birthdate) {
return new LittleCat(name, birthdate, null, null);
}
static LittleCat withNoInformation() {
return new LittleCat("kitty", LocalDate.now(), null, null);
}
private LittleCat(String name, LocalDate birthdate, Cat dad, Cat mom) {
// implementation
}
}
And now the method factory relies on the static factory :
public class Cat extends Animal {
@Override
public ChildAnimal createChild(String name, LocalDate birthdate) {
return LittleCat.withNameAndBirthDate(name, birthdate);
}
}
Upvotes: 2