Composite pattern
From Wikipedia, the free encyclopedia
In computer science, the composite pattern is a partitioning 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 |
[edit] 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 manipulate a group of them. The operations you can perform on all the composite objects often have a least common denominator relationship. For example, if defining a system to portray grouped shapes on a screen, it would be useful to define resizing a group of shapes to have the same effect (in some sense) as resizing a single shape.
[edit] When to use
Composite can be used when clients should ignore the difference between compositions of objects and individual objects.[1] If programmers find that they 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 homogeneous.
[edit] Structure
[edit] 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 component's parent in the recursive structure, and implements it if that's appropriate
[edit] Leaf
- represents leaf objects in the composition
- implements all Component methods
[edit] Composite
- represents a composite Component (component having children)
- implements methods to manipulate children
- implements all Component methods, generally by delegating them to its children
[edit] Example
[edit] Common Lisp
The following example, written in Common Lisp, and translated directly from the Java example below it, implements a method named print-graphic, which can be used on either an ellipse, or a list whose elements are either lists or ellipses.
(defstruct ellipse) ;; An empty struct. ;; For the method definitions, "object" is the variable, ;; and the following word is the type. (defmethod print-graphic ((object null)) NIL) (defmethod print-graphic ((object cons)) (print-graphic (first object)) (print-graphic (rest object))) (defmethod print-graphic ((object ellipse)) (print 'ELLIPSE)) (let* ((ellipse-1 (make-ellipse)) (ellipse-2 (make-ellipse)) (ellipse-3 (make-ellipse)) (ellipse-4 (make-ellipse))) (print-graphic (cons (list ellipse-1 (list ellipse-2 ellipse-3)) ellipse-4)))
[edit] Java
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. In algebraic form,
Graphic = ellipse | GraphicList
GraphicList = empty | Graphic GraphicList
It could be extended to implement several other shapes (rectangle, etc.) and methods (translate, etc.).
import java.util.List; import java.util.ArrayList; /** "Component" */ interface Graphic { //Prints the graphic. public void print(); } /** "Composite" */ class CompositeGraphic implements Graphic { //Collection of child graphics. private List<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); } } /** "Leaf" */ class Ellipse implements Graphic { //Prints the graphic. public void print() { System.out.println("Ellipse"); } } /** Client */ 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(); } }
[edit] Python
class Component(object): def __init__(self, *args, **kw): pass class Leaf(Component): def __init__(self, *args, **kw): Component.__init__(self, *args, **kw) class Composite(Component): def __init__(self, *args, **kw): Component.__init__(self, *args, **kw) self.children = [] def append_child(self, child): self.children.append(child) def remove_child(self, child): self.children.remove(child) c = Composite() l = Leaf() c.append_child(l)
[edit] See also
- Design Patterns (book) - the book that started it all
- Mixin
- Facade pattern
- Decorator pattern
- Law of Demeter
- Delegation pattern
- Builder pattern
- Abstract factory pattern
[edit] External links
- Composite pattern description from the Portland Pattern Repository
- Composite pattern in UML and in LePUS3, a formal modelling language
- Class::Delegation on CPAN
- Chinese Ring Puzzle Applet
- "The End of Inheritance: Automatic Run-time Interface Building for Aggregated Objects" by Paul Baranowski
- PerfectJPattern Open Source Project, Provides componentized implementation of the Composite Pattern in Java
- [1] A persistent Java-based implementation
[edit] References
- ^ a b Gamma, Erich; Richard Helm, Ralph Johnson, John M. Vlissides (1995). Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley. pp. 395. ISBN 0201633612.
|
|
This article's citation style may be unclear. The references used may be made clearer with a different or consistent style of citation, footnoting, or external linking. (September 2009) |
Parts of this article originated from the Perl Design Patterns Book
|
|||||||||||