//
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
***************************************/