Use of factory pattern in Python?

Jan Dries jan.dries at dcube-resource.be
Thu Dec 7 04:31:06 EST 2006



Gabriel Genellina wrote:
> At Thursday 7/12/2006 05:28, Nathan Harmston wrote:
>> so I was thinking of having a factory class to return the individual
>> objects for each row......ie
>>
>> class Factory():
>>         # if passed a gene return a gene object
>>         # if passed an intron return an intron object
>>         # if passed an exom return an exon object
>>
>> Is this a good way of doing this, or is there a better way to do this
>> in Python, this is probably the way I d do it in Java.
> 
> The basic idea is the same, but instead of a long series of 
> if...elif...else you can use a central registry (a dictionary will do) 
> and dispatch on the name. Classes act as their own factories.
> 
> registry = {}
> 
> class Base(object):
>     kind = "Unknown"
> register(Base)
> 
> class Gene(Base):
>     kind = "gene"
>     def __init__(self, *args, **kw): pass
> register(Gene)
> 
> class Intron(Base):
>     kind = "intron"
>     def __init__(self, *args, **kw): pass
> register(Intron)
> 
> def register(cls):
>     registry[cls.kind] = cls
> 
> def factory(kind, *args, **kw):
>     return registry[kind](*args, **kw)
> 

And by using a metaclass on Base you can add the wizardry to have the 
register-function called automatically whenever a class is derived from 
Base. I also tend to use the class name instead of a separate "kind" 
attribute.

registry = {}

class MetaBase(type):
     def __init__(cls, name, bases, dict):
         registry[name] = cls

class Base(object):
     __metaclass__ = MetaBase

class Gene(Base):
     def __init__(self, *args, **kw): pass

class Intron(Base):
     def __init__(self, *args, **kw): pass

def factory(kind, *args, **kw):
     return registry[kind](*args, **kw)


That way you don't have to think about calling the register-function 
each time you derive a new class.

Regards,
Jan



More information about the Python-list mailing list