lundi 27 juillet 2015

Composite Design Pattern Leaf Management

Most of the descriptions of the composite design pattern I have seen have the Composite implement the add() and remove() methods and leave those methods unimplemented in the Leaf objects. For example, the diagram in the Wiki Page on the subject suggests this, which is more or less the same as the GoF diagram.

Regarding implementing these in the parent Component class, the GoF have the following to say:

Defining the child management interface at the root of the class hierarchy gives you transparency, because you can treat all components uniformly. It costs you safety, however, because clients may try to do meaningless things like add and remove objects from leaves.

I agree that having a Leaf implement remove() is strange to handle. (Do you delete yourself? Do you have to implement some sort of NullLeaf object?) But since the point of the pattern is to make Leafs and Composites behave the same way I don't see why add() could be implemented in Component.

My question: Why can't Component at least implement add()? Would doing so violate any key design principles? Does doing so no longer make this a composite design pattern? Below is an example in Python which captures the essence of what I tried to implement in my own work:

class Component:
    def add(self, other):
        # in Python, may be more natural to define __add__
        c = Composite()
        c.children = self.children + other.children
        return c

class Leaf(Component):
    def __init__(self):
        self.children = [self]  # possibly strange?

    def operation(self):
        # operation specific to this leaf

class Composite(Component):
    def __init__(self):
        self.children = []

    def operation(self):
        for child in self.children:
            child.operation()

With an "example usage":

>>> l1 = Leaf()
>>> l2 = Leaf()
>>> c = l1.add(l2)  # c is a `Composite` instance
>>> c.operation()

Aucun commentaire:

Enregistrer un commentaire