Je suis en train de réfléchir a un système permettant a des contributeurs de modifier le comportement de certaines classes d'une application en écrivant des classes filles. Voici un code d'exemple:

Le but est de permettre a des contributeur de modifier le comportement de BaseWorker ou BaseWarrior. Les classes concernés:

baseobjects.py
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
class BaseBug(object):
    def move(self, x, y):
        print 'move', x, y
 
class BaseWorker(BaseBug):
    def work(self):
        print 'work'
 
class BaseWarrior(BaseBug):
    def fight(self):
        print 'fight'
La "Factory" écrite pour permettre ce comportement: Un singleton qui lorsque on lui demande une classe construit un classe pour l'occasion qui hérite (héritage multiple) de toutes les réécritures présente dans les addons.

factory.py
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Factory:
    class __Factory:
 
        def __init__(self):
            self._extend_registry = {}
            self._class_registry = {}
 
        def extend(self, object_name, theclass):
            if object_name not in self._extend_registry:
                self._extend_registry[object_name] = []
            self._extend_registry[object_name].append(theclass)
 
        def get_class(self, object_name):
            if object_name not in self._class_registry:
                # Construction d'une classe etendue a partir des sous classes existantes
                self._class_registry[object_name] = type('Final'+object_name, tuple(self._extend_registry[object_name]), {})
            return self._class_registry[object_name]
 
    instance = None
 
    def __init__(self):
        if not Factory.instance:
            Factory.instance = Factory.__Factory()
    def __getattr__(self, name):
        return getattr(self.instance, name)
Des surcharges, sortes "d'addons" ajoutable/enlevable par l'utilisateur:

spaceobjects.py
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
from factory import Factory
from baseobjects import BaseWorker, BaseWarrior
 
class SpaceWarrior(BaseWarrior):
    def fight(self):
        super(SpaceWarrior, self).fight()
        print 'Se bat dans l\'espace'
 
factory = Factory()
factory.extend('Warrior', SpaceWarrior)
armedobjects.py
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
from factory import Factory
from baseobjects import BaseWorker, BaseWarrior
 
class ArmedWarrior(BaseWarrior):
    def fight(self):
        super(ArmedWarrior, self).fight()
        print 'tire un coup de fusil'
 
factory = Factory()
factory.extend('Warrior', ArmedWarrior)
et l'utilisation du tout:

main.py
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
from factory import Factory
import spaceobjects
import armedobjects
 
factory = Factory()
 
warrior = factory.get_class('Warrior')()
warrior.fight()
warrior.fight() produit:
fight
tire un coup de fusil
Se bat dans l'espace
Avez-vous déjà implémenter quelque-chose dans le genre ? L'ais-je implémenté d'une façon intelligente ou je cours a la catastrophe ? N'y aurais t-il pas un patron de conception existant pour ce cas de figure ?