Removing inheritance (decorator pattern ?)
Diez B. Roggisch
deets at nospam.web.de
Sun Jun 15 16:12:00 EDT 2008
George Sakkis schrieb:
> I have a situation where one class can be customized with several
> orthogonal options. Currently this is implemented with (multiple)
> inheritance but this leads to combinatorial explosion of subclasses as
> more orthogonal features are added. Naturally, the decorator pattern
> [1] comes to mind (not to be confused with the the Python meaning of
> the term "decorator").
>
> However, there is a twist. In the standard decorator pattern, the
> decorator accepts the object to be decorated and adds extra
> functionality or modifies the object's behavior by overriding one or
> more methods. It does not affect how the object is created, it takes
> it as is. My multiple inheritance classes though play a double role:
> not only they override one or more regular methods, but they may
> override __init__ as well. Here's a toy example:
>
> class Joinable(object):
> def __init__(self, words):
> self.__words = list(words)
> def join(self, delim=','):
> return delim.join(self.__words)
>
> class Sorted(Joinable):
> def __init__(self, words):
> super(Sorted,self).__init__(sorted(words))
> def join(self, delim=','):
> return '[Sorted] %s' % super(Sorted,self).join(delim)
>
> class Reversed(Joinable):
> def __init__(self, words):
> super(Reversed,self).__init__(reversed(words))
> def join(self, delim=','):
> return '[Reversed] %s' % super(Reversed,self).join(delim)
>
> class SortedReversed(Sorted, Reversed):
> pass
>
> class ReversedSorted(Reversed, Sorted):
> pass
>
> if __name__ == '__main__':
> words = 'this is a test'.split()
> print SortedReversed(words).join()
> print ReversedSorted(words).join()
>
>
> So I'm wondering, is the decorator pattern applicable here ? If yes,
> how ? If not, is there another way to convert inheritance to
> delegation ?
Factory - and dynamic subclassing, as shown here:
import random
class A(object):
pass
class B(object):
pass
def create_instance():
superclasses = tuple(random.sample([A, B], random.randint(1, 2)))
class BaseCombiner(type):
def __new__(mcs, name, bases, d):
bases = superclasses + bases
return type(name, bases, d)
class Foo(object):
__metaclass__ = BaseCombiner
return Foo()
for _ in xrange(10):
f = create_instance()
print f.__class__.__bases__
Diez
More information about the Python-list
mailing list