The Composite Pattern allows you to compose objects into tree structures to represent part-whole hierarchies.  Composite lets clients treat individual objects and compositions of objects uniformly.  In other words we can ignore the differences between compositions of objects (nodes) and individual objects (leafs).

An example of the Composite Design Pattern follows:

public abstract class MenuComponent {
	getName() { throw new UnsupportedOperationException(); }
	getPrice() { throw new UnsupportedOperationException(); }
	add(Component) { throw new UnsupportedOperationException(); }
	remove(Component) { throw new UnsupportedOperationException(); }
	getChild(int) { throw new UnsupportedOperationException(); }
	abstract Iterator createIterator();
}

public class MenuItem extends MenuComponent {
	
	public Iterator createIterator() {
		return new NullIterator();
	}
	private class NullIterator() implements Iterator {
		public Object next() { return null; }
		public boolean hasNext() { return false; }
		public void remove() { throw new UnsupportedOperationException(); }
	}
}

public class Menu extends MenuComponent {
	ArrayList menuComponents = new ArrayList();
	public void add(MenuComponent c) { menuComponents.add(c): }
	public void remove(MenuComponent c) { menuComponents.remove(c); }
	public Iterator createIterator() { 
		return new CompositeIterator(menuComponents.iterator()); 
	}
}
//  This must handle the recursion through nodes
public class CompositeIterator implements Iterator {
	Stack stack = new Stack();
	
	public CompositeIterator(Iterator iterator) {
		stack.push(iterator);
	}
	
	public Object next() {
		if (hasNext()) {
			Iterator iterator = (Iterator) stack.peek();
			MenuComponent component = (MenuComponent) iterator.next();
			if (component instanceof Menu) {
				stack.push(component.createIterator());
			}
			return component;
		} else {
			return null;
		}
	}
	
	public boolean hasNext() {
		if (stack.empty()) {
			return false;
		} else {
			Iterator iterator = (Iterator) stack.peek();
			if (!iterator.hasNext()) {
				stack.pop();
				return nasNext();
			} else {
				return true;
			}
		}
	}
	
	public void remove() {
		throw new UnsupportedOperationException();
	}
}