- 1. Goals
- 2. Problems
- 3. Discussion
- 4. Structure
- 5. Example
- 6. Control List
- 7. Rules of thumb
Goals
- Arrange objects into tree structures to represent entire parts of the hierarchy. The linker allows clients to treat individual objects and compositions of objects in the same way.
- Recursive composition
- "Directories contain entries, each of which can be a directory."
- One-to-many hierarchy representation
Problems
An application needs to manipulate a hierarchical collection of "primitive" and "composite" objects. The processing of a primitive object is handled in one way, while the processing of a composite object can be handled in different ways. Requesting the type of an object before processing is not desirable.
Discussion
Define an abstract base class (component) that defines the behavior that should be performed in the same way for all primitive and composite objects. Subclass - primitive and composite classes. Each composite object "connects" only to the abstract type of the Component, since it manages its "children".
Use this pattern whenever you have "composites that contain components, each of which can be composited".
Child management methods [ addChild() , removeChild() ] should normally be defined in the Composite class. Unfortunately, the desire to use primitives and composite objects alike requires that these methods be moved to the abstract Component class.
Structure
Composers containing Components, each of which can be composite.
Menus containing menu items, each of which can be a menu.
Row-column GUI layout managers, which contain widgets, each of which can be a row-column GUI layout manager.
Directories containing files, each of which can be a directory.
Containers containing elements, each of which can be a container.
Example
The composer organizes objects into tree structures and allows clients to process individual objects and compositions individually. Although this example is abstract, the arithmetic expressions are Composites. An arithmetic expression consists of an operand, an operator (+ - * /), and another operand. The operand can be a number or another arithmetic expression. So 2 + 3 and (2 + 3) + (4 * 6) are valid expressions.
Control List
- Make sure your problem is in representing tree-like hierarchical relationships.
- Consider an example: "Containers containing devices, each of which can be a container." Divide them into primitive classes and container classes.
- Create an interface to represent the simplest node with the minimum necessary methods makes your containers and primitives interchangeable. It must specify behavior that must be performed in the same way in all primitives and containers.
- All container classes implement the interface.
- All container classes declare a one-to-many relationship with an interface.
- Container classes use polymorphism to delegate their container objects.
- Child management methods [ addChild() , removeChild() ] should normally be defined in the Composite class. Unfortunately, the desire to treat primitives and layouts uniformly may require these methods to be promoted to the abstract Component class.
Rules of thumb
- The composer and decorator have similar structure diagrams, reflecting the fact that both rely on recursive composition to organize an open number of objects.
- The layout can be moved using an iterator. Visitor can apply an operation on layouts. The linker can use Chain of Responsibility to allow components to access global properties through their parent. It can also use a Decorator to override these properties piece by piece. It can use an Observer to bind one object structure to another and state so that the component changes its behavior as the state changes.
- The linker may allow you to create a pick from smaller parts using recursive composition.
- The decorator is for adding properties to objects without a subclass. Hence, the layout and decorator are often used together.
- Flyweight is often combined with Composite to implement common leaf nodes.