Jump to content

Composite pattern

From Wikipedia, the free encyclopedia

This is an old revision of this page, as edited by DCrazy (talk | contribs) at 18:16, 21 October 2007 (Undid revision 166094177 by DCrazy (talk)). The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.

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]

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.[citation needed]

Structure

The class "Component" derives "Composite" and "Leaf". A composite has 0 components or more.
The class "Component" derives "Composite" and "Leaf". A composite has 0 components or more.

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

References

  1. ^ a b 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