Composite pattern
This article needs attention from an expert in Computer science. Please add a reason or a talk parameter to this template to explain the issue with the article. |
In computer science, the composite pattern is a design pattern: "A general solution to a common problem in software design." Composite allows a group of objects to be treated in the same way as a single instance of an object.
Motivation: When dealing with tree-structured data, programmers often have to discriminate between a leaf-node and a branch. This makes code more complex, and therefore, error prone. The solution is an interface that allows treating complex and primitive objects uniformly. In object-oriented programming, a Composite is an object (e.g. a shape) designed as a composition of one-or-more similar objects (other kinds of shapes/geometries), all exhibiting similar functionality. This is known as a "has-a" relationship between objects. The key concept is that you can manipulate a single instance of the object just as you would a group of them. The operations you can perform on all the composite objects often have a least common denominator relationship. For example, when resizing a single shape to fill the screen, surely you would expect/desire that resizing a group of shapes would have the same effect.
When to use: You find that you are using multiple objects in the same way, and often have nearly identical code to handle each of them -- the only differences being that you are manipulating an instance of a 'circle' versus a 'square', for instance. Useful if differentiation doesn't need to exist, and it would be easier to think of them as homogeneous. (Of course, you could still provide functionality to manipulate only a single instance -- like selecting an item from a list instead of operating on the whole list.)
Compose means a special thing: it refers to building objects using DelegationConcept. Delegation-composition hangs onto constituent parts-using references. By contrast, mixins inherit from each part. MixIns prevent returning a WholeObject in response to requests for information, and they prevent having more than one of any given part.
The composite pattern is an object oriented pendant to algebraic data types.
Structure
- Component
-
- is the abstraction for all components, including composite ones
- declares the interface for objects in the composition
- implements default behavior for the interface common to all classes, as appropriate
- declares an interface for accessing and managing its child components
- (optional) defines an interface for accessing a components's parent in the recursive structure, and implements it if that's appropriate
- Leaf
-
- represents leaf objects in the composition
- implements all Component methods
- Composite
-
- represents a composite Component (component having children)
- implements methods to manipulate children
- implements all Component methods, generally by delegating them to its children
Example
The following example, written in Java, implements a graphic class, which can be either an ellipse or a composition of several graphics. Every graphic can be printed.
It could be extended to implement several other shapes (rectangle etc.) and methods (translate etc.).
import java.util.ArrayList;
interface Graphic {
//Prints the graphic.
public void print();
}
class CompositeGraphic implements Graphic {
//Collection of child graphics.
private ArrayList<Graphic> mChildGraphics = new ArrayList<Graphic>();
//Prints the graphic.
public void print() {
for (Graphic graphic : mChildGraphics) {
graphic.print();
}
}
//Adds the graphic to the composition.
public void add(Graphic graphic) {
mChildGraphics.add(graphic);
}
//Removes the graphic from the composition.
public void remove(Graphic graphic) {
mChildGraphics.remove(graphic);
}
}
class Ellipse implements Graphic {
//Prints the graphic.
public void print() {
System.out.println("Ellipse");
}
}
public class Program {
public static void main(String[] args) {
//Initialize four ellipses
Ellipse ellipse1 = new Ellipse();
Ellipse ellipse2 = new Ellipse();
Ellipse ellipse3 = new Ellipse();
Ellipse ellipse4 = new Ellipse();
//Initialize three composite graphics
CompositeGraphic graphic = new CompositeGraphic();
CompositeGraphic graphic1 = new CompositeGraphic();
CompositeGraphic graphic2 = new CompositeGraphic();
//Composes the graphics
graphic1.add(ellipse1);
graphic1.add(ellipse2);
graphic1.add(ellipse3);
graphic2.add(ellipse4);
graphic.add(graphic1);
graphic.add(graphic2);
//Prints the complete graphic (four times the string "Ellipse").
graphic.print();
}
}
See also
- Design Patterns: The book that started it all.
- Mixin
- Facade pattern
- Decorator pattern
- Law of Demeter
- Delegation pattern
- Builder pattern
- Abstract factory pattern
External links
- Description from the Portland Pattern Repository
- Class::Delegation on CPAN
- Chinese Ring Puzzle Applet
- "The End of Inheritance: Automatic Run-time Interface Building for Aggregated Objects" by Paul Baranowski
- Composite Pattern by Vince Huston
- A persistent implementation of the Composite Pattern using Hibernate
- Note the above isn't a representation of the Composite Pattern
- University of Sydney COMP5028 Object Oriented Analysis and Design
References
Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley. 1995. p. 395. ISBN 0201633612. {{cite book}}
: Unknown parameter |coauthors=
ignored (|author=
suggested) (help)
Parts of this article originated from the Perl Design Patterns Book