Jump to content

Composite pattern

From Wikipedia, the free encyclopedia

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

File:Compositepattern.png

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

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