Welcome, guest | Sign In | My Account | Store | Cart

In the factory pattern you have an object that creates other objects.

Python, 73 lines
 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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
"""
A generic factory implementation.
Examples:
>>f=Factory()
>>class A:pass
>>f.register("createA",A)
>>f.createA()
<__main__.A instance at 01491E7C>

>>> class B:
... 	def __init__(self, a,b=1):
... 		self.a=a
... 		self.b=b
... 		
>>> f.register("createB",B,1,b=2)
>>> f.createB()
>>> b=f.createB()
>>> 
>>> b.a
1
>>> b.b
2

>>> class C:
... 	def __init__(self,a,b,c=1,d=2):
... 		self.values = (a,b,c,d)
... 
>>> f.register("createC",C,1,c=3)
>>> c=f.createC(2,d=4)
>>> c.values
(1, 2, 3, 4)

>>> f.register("importSerialization",__import__,"cPickle")
>>> pickle=f.importSerialization()
>>> pickle
<module 'cPickle' (built-in)>
>>> f.register("importSerialization",__import__,"marshal")
>>> pickle=f.importSerialization()
>>> pickle
<module 'marshal' (built-in)>

>>> f.unregister("importSerialization")
>>> f.importSerialization()
Traceback (most recent call last):
  File "<interactive input>", line 1, in ?
AttributeError: Factory instance has no attribute 'importSerialization'
"""

class Factory:      
    def register(self, methodName, constructor, *args, **kargs):
        """register a constructor"""
        _args = [constructor]
        _args.extend(args)
        setattr(self, methodName,apply(Functor,_args, kargs))
        
    def unregister(self, methodName):
        """unregister a constructor"""
        delattr(self, methodName)

class Functor:
    def __init__(self, function, *args, **kargs):
        assert callable(function), "function should be a callable obj"
        self._function = function
        self._args = args
        self._kargs = kargs
        
    def __call__(self, *args, **kargs):
        """call function"""
        _args = list(self._args)
        _args.extend(args)
        _kargs = self._kargs.copy()
        _kargs.update(kargs)
        return apply(self._function,_args,_kargs)
        

Factory is useful to separate implementation from interface. It adds a new indirection layer. When you want to instanciate an object you call its factory and the factory creates the instance.

2 comments

rbeer 20 years, 1 month ago  # | flag

Abstract Factory? Hmm, can't find my go4 - but this looks to me like the _abstract_ factory pattern rather than the factory pattern. Very nice to see another "design pattern"!

Z Liu 14 years, 11 months ago  # | flag

should apply() be replaced. Since apply() is deprecated. Should we:

    setattr(self, methodName, apply(Functor, _args, kargs))

change to:

    setattr(self, methodName, Functor(*_args, **kargs))

and

    return apply(self._function, _args, _kargs)

changed to:

    return self._function(*_args, **_kargs)
Created by Andres Tuells on Tue, 6 Nov 2001 (PSF)
Python recipes (4591)
Andres Tuells's recipes (7)
Recipes I've used (3)

Required Modules

  • (none specified)

Other Information and Tasks