Rififi
Rififi

Reputation: 121

GoF design patterns: different kinds of factory

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

Answers (2)

xenn_33
xenn_33

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

davidxxx
davidxxx

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 :

  • hiding to the clients some implementation details such as the runtime returned object.
  • caching
  • proxying.
  • easing the API usage.
  • replacing the constructors

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

Related Questions