D'après Wikipédia, la fabrique (factory) est un patron de conception (design pattern) qui permet d'instancier des objets dont le type est dérivé d'un type abstrait. La classe exacte de l'objet n'est donc pas connue par l'appelant. Plus simplement, il s'agit d'une fonction qui gère l'instanciation de la bonne classe.

Pour que ça soit plus clair, prenons un cas concrêt : le module Python MSS. Ce module sert à prendre des captures d'écran de manière native, c'est-à-dire en utilisant des appels système et non d'autres modules tiers. Ce qui se traduit par l'utilisation de fonctions propres à chaque système d'exploitation : capturer les pixels d'un écran sur Windows n'est pas du tout pareil sur GNU/Linux ou encore MacOS X. Pour le développeur/utilisateur qui souhaite se servir de ce module, il doit savoir sur quel système d'exploitation il se trouve afin d'importer la bonne classe :

# MacOS X
from mss.darwin import MSS

# GNU/Linux
from mss.linux import MSS

# Windows
from mss.windows import MSS

Chacune de ces classes hérite de la classe parente MSSBase qui fournit les méthodes communes comme l'enregistrement des données dans le fichier final au format PNG.

Résultat : l'import est chiant. Il faudrait faire des imports conditionnels en début de chaque script pour savoir si on se trouve sur le bon système d'exploitation et importer la classe depuis le bon fichier. Misère.

C'est là qu'entre en jeu la factory ! Comment ? En créant une fonction qui se chargera d'importer la bonne classe si disponible, lever une exception le cas échéant (factory.py) :

# Pour savoir sur quel système d'exploitation on se trouve
from platform import system

# Et la factory
def mss(*args, **kwargs):
    os_ = system().lower()

    if os_ == 'darwin':
        from mss.darwin import MSS
    elif os_ == 'linux':
        from mss.linux import MSS
    elif os_ == 'windows':
        from mss.windows import MSS
    else:
        raise ImportError('OS not (yet?) supported.')

    return MSS(*args, **kwargs)

L'import magique se fait tout simplement :

from mss import mss

Ensuite, il suffit d'appeler la factory. Pour cet exemple, l'utilisation du module MSS est simple :

with mss() as screenshotter:
    # ...

Autres design pattern

Sam & Max ont déjà traité ces design pattern :

Enfin, Zeste de Savoir explique bien ce qu'est le pattern dispatcher en Python.


Sources :