Composite
From Wikibooks, open books for an open world
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