Composite

From CSSEMediaWiki
(Difference between revisions)
Jump to: navigation, search
Line 52: Line 52:
 
*[[Iterator]]: This pattern can be used to traverse composites.
 
*[[Iterator]]: This pattern can be used to traverse composites.
 
*[[Visitor]]: This pattern can be used to pull out behavior that would usually be in the Composite and Leaf classes.
 
*[[Visitor]]: This pattern can be used to pull out behavior that would usually be in the Composite and Leaf classes.
 +
 +
==Conflicts==
 +
* [[Avoid no-op overrides]]: The Composite pattern tells us to put the addChild(), removeChild() and getChildren() methods in the Component class. However, this means that we need to override them using a no-op in the leaf component which violates Riel's heuristic [[Avoid no-op overrides]] and smells a little of [[Refused bequest smell]].
  
 
== See also ==
 
== See also ==

Revision as of 03:39, 3 August 2009

Composite pattern

The Composite pattern is useful whenever one has a class which may contain instances of itself. Common computer science examples are nodes in a tree structure, or shapes in a graphical model. More concrete physical world examples include regions (which can potentially contain many smaller regions), schools of fish (where those fish may swim, eat, etc in a collective fashion), and divisions/teams in a workplace.

The key feature of this pattern is a subclass which both extends the superclass, and contains (though an aggregation or composition relationship) a number of instances of the superclass.

The advantage gained from this structure is that we can transparently use a Composite Instance just as with a Primitive instance. shape.draw(), for example could draw any shape, from a primitive to a highly complex diagram or model.


Contents

Features

Classes

  • Interface (Abstract class) that represents Component.
  • Concrete Composite class that implements Component.
  • Concrete leaf class that implements Component.
  • Client class.

Attribute

  • Composite maintains a collection of Components. E.g, Collection<Component>

Methods

  • Component has abstract methods to add and remove an Component to and from.
  • Composite has concrete method to add an instance of Component that shared by Composites and leaves on the collection.
  • Composite has concrete method to remove an instance of Component that shared by Composites and leaves from the collection.

Relationships

  • Composite contains both Composite and leaf as Component.
  • All Composites and leaves are seen as Component by Client.

Use When

  • You want to represent a hierarchy of parts and whole objects.
  • You want clients to not know about whether they are dealing with a composition of objects or a single object.

Recognising the pattern

Classes: Composite, Component, multiple Leaves

  • Inheritance hierarchy that has a Component interface
  • Component interface has declarations for add() and remove() methods for adding/removing Components.
  • Composite class has private collection of Components.

Consequences

  • Primitive objects can be composed into more complex objects, which in turn can be composed into even more complex objects. Clients treat primitive objects and composite objects in the same way.
  • Simplifies the client because it can treat simple objects and composites the same way.
  • Makes it easy to add new components or composites because the client code will not be affected.
  • Can make the design too general because it is hard to restrict what components can be added to composites.

Related Patterns

  • Chain of Responsibility: This pattern often uses a component-parent link.
  • Decorator: This pattern is often used together with Composite.
  • Flyweight: This pattern lets you share components.
  • Iterator: This pattern can be used to traverse composites.
  • Visitor: This pattern can be used to pull out behavior that would usually be in the Composite and Leaf classes.

Conflicts

  • Avoid no-op overrides: The Composite pattern tells us to put the addChild(), removeChild() and getChildren() methods in the Component class. However, this means that we need to override them using a no-op in the leaf component which violates Riel's heuristic Avoid no-op overrides and smells a little of Refused bequest smell.

See also


Personal tools