3

Here's how I understand the composite pattern:

In the composite pattern, a root object is composed of objects which may be further composed. Moreover, to be considered composite, all those objects expose a common interface.

My question appears twice in italics below. An example given by a mentor of mine is a filesystem represented by objects:

interface Node {
  public int size();
}

class Folder implements Node {
  List<Node> contents;

  public int size() {
    int size = 0;
    for (Node n : contents)
      size += n.size();

    return size;
  }
}

class File implements Node {
  int size;

  public int size() {
    return size;
  }
}

This seems pretty clean. It has a nice property that I'm wondering about:

  • A size() call on Folder calls size() on all member Nodess, there is no condition guarding size() calls on member Nodes. If there were a condition guarding size() calls on children Nodes, would the structure no longer be Composite pattern?

To clarify, I'll give another example. Say a Person object can grab(), and Person is composed of 2 Hands and 1 Mouth. Both Hand and Mouth can grab(). On an instance of Person, calling person.grab() will call grab() on one of its members capable of grab(). For instance, the left Hand will grab() if the right Hand is already full, and both Hand will grab if the object is heavy.

Is that Composite pattern, even though there are conditional guards on member calls?

5

The composite pattern is a good choice for (recursive) tree-like structures, where the clients want to use operations from the interface without actually knowing if something is a composite or a leaf. In other words, they are expecting the derived classes to confirm to the Liskov substitution principle. What does not matter is how the operations are implemented internally.

So your Person example is not a bad choice for the composite pattern because its internal grab implementation contains a conditional. It is a bad choice because a Person is not a recursive tree-like object. It may be composed of hands and mouth, but not of other Person objects, and I do not see a good term which would qualify as a common base class for Person and Hand, or a use case where a client can ignore the fact he is asking a person to grab, or a hand.

  • 1
    I suppose Person and Hand could both implement a Grabber interface, but that feels like a contrivance to shoehorn self-similarity where it doesn't belong. Thanks for the answer! – kdbanman Mar 14 '15 at 4:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.