Composite

From Wikibooks, open books for an open world
Jump to: navigation, search

Bridge Computer Science Design Patterns
Composite
Decorator

Various examples of the composite pattern.

Implementation in 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.).

/** "Component" */
interface Graphic {
 
    // Prints the graphic.
    public void print();
}
/** "Composite" */
import java.util.List;
import java.util.ArrayList;
 
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();
    }
}
Implementation in C#
using System;
using System.Collections.Generic;
 
namespace Composite
{
    class Program
    {
        interface IGraphic
        {
            void Print();
        }
 
        class CompositeGraphic : IGraphic
        {
            private List<IGraphic> child = new List<IGraphic>();
 
            public CompositeGraphic(IEnumerable<IGraphic> collection)
            {
                child.AddRange(collection);
            }
 
            public void Print()
            {
                foreach(IGraphic g in child)
                {
                    g.Print();
                }
            }
        }
 
        class Ellipse : IGraphic
        {
            public void Print()
            {
                Console.WriteLine("Ellipse");
            }
        }
 
        static void Main(string[] args)
        {
            new CompositeGraphic(new IGraphic[]
                {
                    new CompositeGraphic(new IGraphic[]
                        {
                            new Ellipse(),
                            new Ellipse(),
                            new Ellipse()
                        }),
                    new CompositeGraphic(new IGraphic[]
                        {
                            new Ellipse()
                        })
                }).Print();
        }
    }
}
Implementation in 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)))
Implementation in PHP
<?php
 
/** "Component" */
interface Graphic
{
    /**
     * Prints the graphic
     *
     * @return void
     */
    public function printOut();
}
 
/**
 * "Composite" - Collection of graphical components
 */
class CompositeGraphic implements Graphic
{
    /**
     * Collection of child graphics
     *
     * @var array
     */
    private $childGraphics = array();
 
    /**
     * Prints the graphic
     *
     * @return void
     */
    public function printOut()
    {
        foreach ($this->childGraphics as $graphic) {
            $graphic->printOut();
        }
    }
 
    /**
     * Adds the graphic to the composition
     *
     * @param Graphic $graphic Graphical element
     *
     * @return void  
     */
    public function add(Graphic $graphic)
    {
        $this->childGraphics[] = $graphic;
    }
 
    /**
     * Removes the graphic from the composition
     *
     * @param Graphic $graphic Graphical element
     *
     * @return void
     */
    public function remove(Graphic $graphic)
    {
        if (in_array($graphic, $this->childGraphics)) {
            unset($this->childGraphics[array_search($graphic, $this->childGraphics)]);
        }
    }
}
 
/** "Leaf" */
class Ellipse implements Graphic
{
    /**
     * Prints the graphic
     *
     * @return void
     */
    public function printOut()
    {
        echo "Ellipse";
    }
}
 
/** Client */
 
//Initialize four ellipses
$ellipse1 = new Ellipse();
$ellipse2 = new Ellipse();
$ellipse3 = new Ellipse();
$ellipse4 = new Ellipse();
 
//Initialize three composite graphics
$graphic = new CompositeGraphic();
$graphic1 = new 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->printOut();
Implementation in Python
class Component(object):
    def __init__(self, *args, **kw):
        pass
 
    def component_function(self): pass
 
class Leaf(Component):
    def __init__(self, *args, **kw):
        Component.__init__(self, *args, **kw)
 
    def component_function(self):
        print "some function"
 
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)
 
    def component_function(self):
        map(lambda x: x.component_function(), self.children)
 
c = Composite()
l = Leaf()
l_two = Leaf()
c.append_child(l)
c.append_child(l_two)
c.component_function()
Implementation in Ruby
module Component
  def do_something
    raise NotImplementedError
  end
end
 
class Leaf
  include Component
  def do_something
    puts "Hello"
  end
end
 
class Composite
  include Component
  attr_accessor :children
  def initialize
    self.children = []
  end
  def do_something
    children.each {|c| c.do_something}
  end
  def append_child(child)
    children << child
  end
  def remove_child(child)
    children.delete child
  end
end
 
composite = Composite.new
leaf_one = Leaf.new
leaf_two = Leaf.new
composite.append_child(leaf_one)
composite.append_child(leaf_two)
composite.do_something


Clipboard

To do:
Add more illustrations.


Bridge Computer Science Design Patterns
Composite
Decorator


You have questions about this page?
Ask it here:


Create a new page on this book: