multiple extensions to a class

Jeff Shannon jeff at ccvcorp.com
Mon Jul 12 16:16:48 EDT 2004


Humpty Dumpty wrote:

>From: "David Fraser" <davidf at sjsoft.com>
>
>  
>
>>Jeff Shannon wrote:
>>    
>>
>>>You might consider making class A into a container of some sort -- i.e.,
>>>give it someplace to store a list of "decorator" objects, and then make
>>>B, C, and D into such decorators (rather than subclasses of A).  You'll
>>>have to arrange some way of dispatching messages to A that are intended
>>>for the decorators, and possibly some way for the decorators to talk to
>>>each other.
>>>      
>>>
>
>Interesting idea, could be done... how does this differ from the mixin
>approach?
>  
>

Mixins are all derived from the parent class.  Combining multiple mixins 
requires (as you've noted) knowing ahead of time which combinations 
you'll need, and creating a derived class that includes all of the 
necessary mixins.  (Python does include enough facilities that you could 
do this at runtime, but I'm personally rather leery about using this 
level of deep magic unless it's truly necessary.)

Decorators, on the other hand, are designed to work with a particular 
class, but are not linked directly in an inheritance tree.  There might 
be a fair amount of coupling between the decorator and the class that 
it's designed to decorate, but not necessarily.  (IIRC, the Gang of Four 
used an example based on a windowing toolkit -- a "border" class could 
be designed as a decorator; it wouldn't care what variety of "window" 
class it was decorating, and the "window" class wouldn't care what 
variety of "border" it carried.  The communication protocol between them 
would be fairly straightforward and wouldn't depend on the specific 
implementation of either the decorator or the decorated class.) 

>Yes, but you have to be careful with that in terms of cohesion: though you
>want to allow for extendability through plug-ins, you don't want to
>encourage a mish mash of unrelated classes that send messages around. It's a
>technique to keep in mind, but I want to maintain aggregation of logic and
>function and data as much as possible, ie aim for "the right balance" :)
>  
>

Definitely a balance to be had, here.  On the whole, though, I don't see 
an overgrown inheritance tree to be more maintainable than coherent set 
of decorators.  Whether the classes are related or not makes scant 
difference when there's a mish-mash of them sending messages around. ;)  
To my mind, an inherited mixin class is conceptually no simpler than an 
aggreggated helper class, and depending on the specific application 
aggreggated helpers may result in a cleaner, less-cluttered design.  In 
particular, for the case where varying sets of additional features will 
be needed and those needs won't be known until runtime (i.e., your 
case), aggreggation is better able to deal with the dynamic nature of 
the requirements.

What I'm envisioning is a system wherein class A contains a list of 
decorators.  You could probably add and remove decorators at will; 
certainly it'd be trivial to pass a list of decorators when A is 
instantiated.  Now, whenever a significant state change occurs in A, it 
will iterate over that list, calling a generic method on each decorator 
and passing itself as a parameter:

    for dec in self.decorators:
        dec.Go(self)

Then the Go() method on each decorator can inspect class A for the 
attributes that it understands, and act on them as appropriate.  This 
does require some coupling between A and the decorators, as they must 
both follow a particular protocol, but it doesn't require that either 
side of the protocol be a specific class.  This means that if you later 
extend A in another way, all subclasses of A will work with the same set 
of decorators that A does... and a complete replacement for A, not 
rooted in the same inheritance tree, will work just as well.

Jeff Shannon
Technician/Programmer
Credit International




More information about the Python-list mailing list