0

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:

  • Border b1 = BorderFactory.createLineBorder(Color.RED)
  • Border b2 = BorderFactory.createTitledBorder("Hello")

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.

jaco0646
  • 15,303
  • 7
  • 59
  • 83
Rififi
  • 121
  • 1
  • 11
  • The difference between various factory patterns is one of the most common questions in the design-patterns tag here on SO. I recommend searching within the tag, as this topic has been discussed many many times. My comparison is [here](https://stackoverflow.com/a/50786084/1371329). – jaco0646 Jan 11 '19 at 14:42
  • I've collected several related links in another answer [here](https://stackoverflow.com/a/38667511/1371329). – jaco0646 Jan 11 '19 at 15:04

2 Answers2

2

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);
    }
}
davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • If I understand, the Factory Method not only relies on creating objects which concrete type depend on input parameters. Factory Method relies also on Template Method and Strategy pattern (for the caller). So, in other words, the Factory Method is an Abstract Factory which object family is composed of one kind of member (with potentially multiple subclasses). I'm right ? – Rififi Jan 11 '19 at 10:27
  • For instance, I use something I call "Factory Method" in case of the interpreter pattern (generate object tree from source code). And I'm using "Abstract Factory" for instance in case of games with multiple kinds of enemies and their behaviour dpeend on the difficulty level (so an abstract class providing createEnemyType1() ... createEnemyTypeN() and a subclass for each kind of difficulty). And if I understand, what is called "Factory" is a Factory Method used with Strategy (setFactory(...)) ? – Rififi Jan 11 '19 at 11:00
  • Your example on the Abstract factory and the families of objects is right. But for some other points I disagree. It is the reverse : Template Method and Abstract Factory rely on Method factory. Method factory is "just" the delegation to the creation of some objects to the subclasses. – davidxxx Jan 11 '19 at 17:03
  • Thanks! I encoutered rarely this kind of use case (ChildAnimal), that's why I don't see concrete use cases of Factory Method. Sometimes I use parametric class in this situation (class Cat extends Animal) and the creational method using eventually a static factory internally. So, with parametric the concrete type is known (except if there is subclasses for LittleCat) and I don't see how it can be considered as a factory pattern. About Template Method and Abstract Factory, I said that because Template Method can be used for other purposes (algorithm families/framework behavior). – Rififi Jan 14 '19 at 09:06
1

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.

xenn_33
  • 855
  • 1
  • 10
  • 25
  • Thank you for your reply. Ok didn't know that GoF categories has changed but I understand that patterns are only examples of proven solutions but not rules to follow at all costs. I've asked myself since I saw different versions of the Factory pattern (english vs french presentations). So, you said that the Factory is a method that returns an object, that is an instance of a subclass of the method return type, but this behvior does not requires necessarily the use of factory subclasses. Am I right ? – Rififi Jan 14 '19 at 09:25
  • For instance, I'm using a basic parser for a custom language (DSL) which recognize instructions and use a method StatementFactory.create(String value). This method enumerates string values and instanciate the associated subclass of Statement class. If the string value is a composed value, the create() method decompose the value and recall itself to produce a composite Statement. Is this behavior considered as a example of the Factory GoF pattern in this new classification you mentioned ? – Rififi Jan 14 '19 at 09:29
  • I’d say that yes. The whole idea is the encapsulation of initialization logic if this logic is sophisticated enough for NOT being presented in constructor or invocation of this logic is sophisticated enough so that API users should call something else than direct classes’ constructors. However, you may consider other alternatives to this API – i.e. Statement.CreateFromString(String value) or StatementParser.ParseString(String value). The first option will be more similar to conventional factory (‘create’ word), the second will be more close to the problem domain and less close to OOP paradigms – xenn_33 Jan 14 '19 at 09:48