// Purpose. Composite design pattern // 1. Create a "lowest common denominator" that makes classes interchangeable // 2. All concrete classes declare an "isa" relationship to the interface // 3. All "container" classes couple themselves to the interface // 4. "Container" classes use polymorphism as they delegate to their children interface Component { void traverse(); } // 1. "lowest common denominator" class Primitive implements Component { // 2. "Isa" relationship private int value; public Primitive( int val ) { value = val; } public void traverse() { System.out.print( value + " " ); } } abstract class Composite implements Component { // 2. "Isa" relationship private Component[] children = new Component[9]; // 3. Couple to interface private int total = 0; private int value; public Composite( int val ) { value = val; } public void add( Component c ) { children[total++] = c; } // 3. Couple to public void traverse() { // interface System.out.print( value + " " ); for (int i=0; i < total; i++) children[i].traverse(); // 4. Delegation and polymorphism } } class Row extends Composite { // Two different kinds of "con- public Row( int val ) { super( val ); } // tainer" classes. Most of the public void traverse() { // "meat" is in the Composite System.out.print( "Row" ); // base class. super.traverse(); } } class Column extends Composite { public Column( int val ) { super( val ); } public void traverse() { System.out.print( "Col" ); super.traverse(); } } public class CompositeDemo { public static void main( String[] args ) { Composite first = new Row( 1 ); // Row1 Composite second = new Column( 2 ); // | Composite third = new Column( 3 ); // +-- Col2 Composite fourth = new Row( 4 ); // | | Composite fifth = new Row( 5 ); // | +-- 7 first.add( second ); // +-- Col3 first.add( third ); // | | third.add( fourth ); // | +-- Row4 third.add( fifth ); // | | | first.add( new Primitive( 6 ) ); // | | +-- 9 second.add( new Primitive( 7 ) ); // | +-- Row5 third.add( new Primitive( 8 ) ); // | | | fourth.add( new Primitive( 9 ) ); // | | +-- 10 fifth.add( new Primitive(10 ) ); // | +-- 8 first.traverse(); // +-- 6 } } // Row1 Col2 7 Col3 Row4 9 Row5 10 8 6 // Purpose. Composite design pattern. A static attribute in the Entity // base class can be manipulated by each Box object to control indentation. import java.util.List; import java.util.ArrayList; abstract class Entity { protected static StringBuffer indent = new StringBuffer(); public abstract void traverse(); } class Product extends Entity { private int value; public Product( int val ) { value = val; } public void traverse() { System.out.println( indent.toString() + value ); } } class Box extends Entity { private List children = new ArrayList(); private int value; public Box( int val ) { value = val; } public void add( Entity c ) { children.add( c ); } public void traverse() { System.out.println( indent.toString() + value ); indent.append( " " ); for (int i=0; i < children.size(); i++) ((Entity)children.get(i)).traverse(); indent.setLength( indent.length() - 3 ); } } public class CompositeLevels { public static void main( String[] args ) { Box root = initialize(); root.traverse(); } private static Box initialize() { Box[] nodes = new Box[7]; nodes[1] = new Box( 1 ); int[] s = { 1, 4, 7 }; for (int i=0; i < 3; i++) { nodes[2] = new Box( 21+i ); nodes[1].add( nodes[2] ); int lev = 3; for (int j=0; j < 4; j++) { nodes[lev-1].add( new Product( lev*10 + s[i] ) ); nodes[lev] = new Box( lev*10 + s[i]+1 ); nodes[lev-1].add( nodes[lev] ); nodes[lev-1].add( new Product( lev*10 + s[i]+2 ) ); lev++; } } return nodes[1]; } } /**************** 1 21 31 32 41 42 51 52 61 62 63 53 43 33 22 34 35 44 45 54 55 64 65 66 56 46 36 23 37 38 47 48 57 58 67 68 69 59 49 39 ****************/ // Purpose. User-configurable "views" of a Composite. A second static // attribute is used to remember the "current level" of the traversal. import java.util.List; import java.util.ArrayList; abstract class Entity { protected static StringBuffer indent = new StringBuffer(); protected static int level = 1; public abstract void traverse( int[] levels ); protected boolean printThisLevel( int[] levels ) { for (int i=0; i < levels.length; i++) if (level == levels[i]) return true; return false; } } class Product extends Entity { private int value; public Product( int val ) { value = val; } public void traverse( int[] levels ) { if (printThisLevel( levels )) System.out.println( indent.toString() + value ); } } class Box extends Entity { private List children = new ArrayList(); private int value; public Box( int val ) { value = val; } public void add( Entity c ) { children.add( c ); } public void traverse( int[] levels ) { if (printThisLevel( levels )) { System.out.println( indent.toString() + value ); indent.append( " " ); } level++; for (int i=0; i < children.size(); i++) ((Entity)children.get(i)).traverse( levels ); level--; if (printThisLevel( levels )) indent.setLength( indent.length() - 3 ); } } public class CompositeLevelsAns { public static void main( String[] args ) { Box root = initialize(); int[] levels = new int[args.length]; for (int i=0; i < args.length; i++) levels[i] = Integer.parseInt( args[i] ); root.traverse( levels ); } private static Box initialize() { Box[] nodes = new Box[7]; nodes[1] = new Box( 1 ); int[] s = { 1, 4, 7 }; for (int i=0; i < 3; i++) { nodes[2] = new Box( 21+i ); nodes[1].add( nodes[2] ); int lev = 3; for (int j=0; j < 4; j++) { nodes[lev-1].add( new Product( lev*10 + s[i] ) ); nodes[lev] = new Box( lev*10 + s[i]+1 ); nodes[lev-1].add( nodes[lev] ); nodes[lev-1].add( new Product( lev*10 + s[i]+2 ) ); lev++; } } return nodes[1]; } } /*************************************** D:\java> java CompositeLevelsAns 2 4 6 21 41 42 61 62 63 43 22 44 45 64 65 66 46 23 47 48 67 68 69 49 D:\java> java CompositeLevelsAns 3 6 31 32 61 62 63 33 34 35 64 65 66 36 37 38 67 68 69 39 D:\java> java CompositeLevelsAns 1 2 3 4 5 6 1 21 31 32 41 42 51 52 61 62 63 53 43 33 22 34 35 44 45 54 55 64 65 66 56 46 36 23 37 38 47 48 57 58 67 68 69 59 49 39 ***************************************/