组合模式:允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合
本质上就是以树形的数据结构来完成数据的存储, 而对其的遍历就是对树形结构的遍历。
案例:带有子菜单的菜单
为了可以让客户以一致的方式处理,我们自然而然的就需要菜单和菜单项多继承同一个抽象基类
代码:
import java.util.Iterator;
public abstract class MenuComponent {
public String getName() {
throw new UnsupportedOperationException();
}
public String getDescription() {
throw new UnsupportedOperationException();
}
public double getPrice() {
throw new UnsupportedOperationException();
}
public boolean isVegetarian() {
throw new UnsupportedOperationException();
}
public void add(MenuComponent component) {
throw new UnsupportedOperationException();
}
public void remove(MenuComponent component) {
throw new UnsupportedOperationException();
}
public MenuComponent getChild(int i) {
throw new UnsupportedOperationException();
}
public void print() {
throw new UnsupportedOperationException();
}
public Iterator createIterator() {
throw new UnsupportedOperationException();
}
}
import java.util.ArrayList;
import java.util.Iterator;
public class Menu extends MenuComponent {
private String name;
private String description;
private ArrayList<MenuComponent> list;
public Menu(String name, String description) {
this.name = name;
this.description = description;
list = new ArrayList<MenuComponent>();
}
@Override
public String getName() {
return name;
}
@Override
public String getDescription() {
return description;
}
@Override
public void add(MenuComponent component) {
list.add(component);
}
@Override
public void remove(MenuComponent component) {
list.remove(component);
}
@Override
public MenuComponent getChild(int i) {
return (MenuComponent)list.get(i);
}
@Override
public void print() {
System.out.println("Menu: name = " + name + ", subItems below: ");
Iterator i = list.iterator();
while (i.hasNext()) {
MenuComponent menuComponent = (MenuComponent)i.next();
menuComponent.print();
}
}
@Override
public Iterator createIterator() {
return new MenuComponentIterator(list.iterator());
}
}
import java.util.Iterator;
public class MenuItem extends MenuComponent {
private String name;
private String description;
private boolean vegetarian;
private double price;
public MenuItem(String name, String description, boolean vegetarian, double price) {
this.name = name;
this.description = description;
this.vegetarian = vegetarian;
this.price = price;
}
@Override
public String getName() {
return name;
}
@Override
public String getDescription() {
return description;
}
@Override
public boolean isVegetarian() {
return vegetarian;
}
@Override
public double getPrice() {
return price;
}
@Override
public void print() {
System.out.println("Menu item: name = " + name + ", price = " + price);
}
@Override
public Iterator createIterator() {
return null;
}
}
import java.util.Iterator;
import java.util.Stack;
public class MenuComponentIterator implements Iterator {
private Stack<Iterator> stack;
public MenuComponentIterator(Iterator iterator) {
if (stack == null) {
stack = new Stack<Iterator>();
}
stack.push(iterator);
}
@Override
public boolean hasNext() {
if (stack.isEmpty()) {
return false;
} else {
Iterator iterator = (Iterator)stack.peek();
if (!iterator.hasNext()) {
stack.pop();
return hasNext();
} else {
return true;
}
}
}
@Override
public Object next() {
if (hasNext()) {
Iterator iterator = (Iterator)stack.peek();
MenuComponent menuComponent = (MenuComponent)iterator.next();
if (menuComponent instanceof Menu) {
stack.push(menuComponent.createIterator());
}
return menuComponent;
} else {
return null;
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
public class PatternDemo {
public static void main(String[] args) {
Menu allMenu = new Menu("All menu", "");
MenuItem menuItem = new MenuItem("Hot dog", "", false, 2.39);
MenuItem subMenuItem = new MenuItem("V BLT", "", false, 2.39);
MenuItem subMenuItem1 = new MenuItem("V1", "", true, 1.39);
MenuItem subMenuItem2 = new MenuItem("BLT", "", true, 3.39);
Menu subMenu = new Menu("Sub menu", "sub menu");
allMenu.add(menuItem);
subMenu.add(subMenuItem);
subMenu.add(subMenuItem1);
subMenu.add(subMenuItem2);
allMenu.add(subMenu);
allMenu.print();
}
}
这里两个地方用到了递归,print()方法以及MenuComponentIterator的实现里面。