|
|
This article or section is in need of attention from an expert on the subject. WikiProject Computer science may be able to help recruit one. |
In computer science, the composite pattern is a structural design pattern. Composite allows a group of objects to be treated in the same way as a single instance of an object. The intent of Composite is to "compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions uniformly."[1]
Contents |
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
Composite can be used when clients should ignore the difference between compositions of objects and individual objects.[1]. If you find that you are using multiple objects in the same way, and often have nearly identical code to handle each of them, then Composite is a good choice; it is less complex in this situation to treat primitives and composites as homogenous. 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.). <source lang=java> 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();
}
} </source> C++ Example <source lang="cpp">
- include <iostream>
- include <vector>
using namespace std; class Component { public: virtual void traverse() = 0; }; class Primitive : public Component {
int value;
public:
Primitive( int val ) { value = val; }
void traverse() { cout << value << " "; }
}; class Composite : public Component {
vector<Component*> children; int value;
public:
Composite( int val ) { value = val; }
void add( Component* c ) { children.push_back( c ); }
void traverse() {
cout << value << " ";
for (int i=0; i < children.size(); i++)
children[i]->traverse();
} }; class Row : public Composite { public: // Two different kinds of "con-
Row( int val ) : Composite( val ) { } // tainer" classes. Most of the
void traverse() { // "meat" is in the Composite
cout << "Row"; // base class.
Composite::traverse();
} }; class Column : public Composite { public:
Column( int val ) : Composite( val ) { }
void traverse() {
cout << "Col";
Composite::traverse();
} }; void main( void ) {
Row first( 1 ); // Row1
Column second( 2 ); // |
Column third( 3 ); // +-- Col2
Row fourth( 4 ); // | |
Row fifth( 5 ); // | +-- 7
first.add( &second ); // +-- Col3
first.add( &third ); // | |
third.add( &fourth ); // | +-- Row4
third.add( &fifth ); // | | |
first.add( &Primitive( 6 ) ); // | | +-- 9
second.add( &Primitive( 7 ) ); // | +-- Row5
third.add( &Primitive( 8 ) ); // | | |
fourth.add( &Primitive( 9 ) ); // | | +-- 10
fifth.add( &Primitive(10 ) ); // | +-- 8
first.traverse(); cout << '\n'; // +-- 6
} </source>
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 discussion with 1-page examples 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
- Jt J2EE Pattern Oriented Framework
References
- ^ a b (1995) Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley, 395. ISBN 0201633612.
| The references in this article would be clearer with a different or consistent style of citation, footnoting, or external linking. |
Parts of this article originated from the Perl Design Patterns Book
|
|
|---|
|
Creational: Abstract factory • Builder • Factory • Prototype • Singleton |


