组合模式笔记:
定义:
允许你将对象组成树形结构来表现“整体/部分”的层次结构。组合能让客户以一致的方式处理个别对象和对象组合。
例子:
节点 MenuComponent:
public abstract class MenuComponent { <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>/** 组合方法开始 */ <span style="white-space:pre"> </span>public void add(MenuComponent menuComponent){ <span style="white-space:pre"> </span>throw new UnsupportedOperationException(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public void remove(MenuComponent menuComponent){ <span style="white-space:pre"> </span>throw new UnsupportedOperationException(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>public MenuComponent getChild(int i){ <span style="white-space:pre"> </span>throw new UnsupportedOperationException(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>/** 组合方法结束 */ <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>/** 操作方法开始 */ <span style="white-space:pre"> </span>public String getName(){ <span style="white-space:pre"> </span>throw new UnsupportedOperationException(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>public String getDescription(){ <span style="white-space:pre"> </span>throw new UnsupportedOperationException(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>public double getPrice(){ <span style="white-space:pre"> </span>throw new UnsupportedOperationException(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>public boolean isVegetarian(){ <span style="white-space:pre"> </span>throw new UnsupportedOperationException(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>public void print(){ <span style="white-space:pre"> </span>throw new UnsupportedOperationException(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>/** 操作方法结束 */ <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>public Iterator<MenuComponent> createIterator(){ <span style="white-space:pre"> </span>throw new UnsupportedOperationException(); <span style="white-space:pre"> </span>} }
子节点 (Menu):
public class Menu extends MenuComponent{ <span style="white-space:pre"> </span>Iterator<MenuComponent> iterator = null; <span style="white-space:pre"> </span>ArrayList<MenuComponent> menuComponents = new ArrayList<MenuComponent>(); <span style="white-space:pre"> </span>String name; <span style="white-space:pre"> </span>String description; <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>public Menu(String name,String description){ <span style="white-space:pre"> </span>this.name = name; <span style="white-space:pre"> </span>this.description = description; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>public void add(MenuComponent menuComponent){ <span style="white-space:pre"> </span>menuComponents.add(menuComponent); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>public void remove(MenuComponent menuComponent){ <span style="white-space:pre"> </span>menuComponents.remove(menuComponent); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>public MenuComponent getChild(int i){ <span style="white-space:pre"> </span>return (MenuComponent)menuComponents.get(i); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>public String getName(){ <span style="white-space:pre"> </span>return name; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>public String getDescription(){ <span style="white-space:pre"> </span>return description; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>public void print(){ <span style="white-space:pre"> </span>System.out.print("\n" + getName()); <span style="white-space:pre"> </span>System.out.println("," + getDescription()); <span style="white-space:pre"> </span>System.out.println("---------------------"); <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>Iterator<MenuComponent> iterator = menuComponents.iterator(); //<span style="white-space:pre"> </span>Iterator iterator = createIterator(); <span style="white-space:pre"> </span>while(iterator.hasNext()){ <span style="white-space:pre"> </span>MenuComponent menuComponent = (MenuComponent) iterator.next(); <span style="white-space:pre"> </span>menuComponent.print(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> <span style="white-space:pre"> </span>public Iterator<MenuComponent> createIterator(){ //<span style="white-space:pre"> </span>print(); //<span style="white-space:pre"> </span>System.out.println("List size : " + menuComponents.size()); //<span style="white-space:pre"> </span>return menuComponents.iterator(); <span style="white-space:pre"> </span>if(iterator ==null){ <span style="white-space:pre"> </span>iterator = new CompositeIterator(menuComponents.iterator()); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>return iterator; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> }
菜单项
public class MenuItem extends MenuComponent { String name; String description; boolean vegetarian; double price; public MenuItem(String name,String description,boolean vegetarian,double price){ this.name = name; this.description = description; this.vegetarian = vegetarian; this.price = price; } public String getName(){ return name; } public String getDescrpiton(){ return description; } public double getPrice(){ return price; } public boolean isVegetarian(){ return vegetarian; } public void print(){ System.out.print(" " + getName()); if(isVegetarian()){ System.out.print("(v)"); } System.out.print(", " + getPrice()); System.out.println(" -- " + getDescrpiton()); } public Iterator createIterator(){ return new NullIterator(); } }
自定义迭代器:
package factory.grouppattern; import java.util.Iterator; import java.util.Stack; public class CompositeIterator implements Iterator<MenuComponent> { <span style="white-space:pre"> </span>Stack<Iterator<MenuComponent>> stack = new Stack<Iterator<MenuComponent>>(); <span style="white-space:pre"> </span>public CompositeIterator(Iterator<MenuComponent> iterator) { <span style="white-space:pre"> </span>stack.push(iterator); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>@Override <span style="white-space:pre"> </span>public boolean hasNext() { <span style="white-space:pre"> </span>if(stack.empty()){ <span style="white-space:pre"> </span>return false; <span style="white-space:pre"> </span>}else{ <span style="white-space:pre"> </span>Iterator<MenuComponent> iterator = (Iterator<MenuComponent>)stack.peek(); <span style="white-space:pre"> </span>if(!iterator.hasNext()){ <span style="white-space:pre"> </span>stack.pop(); <span style="white-space:pre"> </span>return hasNext(); <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>else{ <span style="white-space:pre"> </span>return true; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>@Override <span style="white-space:pre"> </span>public MenuComponent next() { <span style="white-space:pre"> </span>if (hasNext()) { <span style="white-space:pre"> </span>Iterator<MenuComponent> iterator = stack.peek(); <span style="white-space:pre"> </span>MenuComponent component = iterator.next(); <span style="white-space:pre"> </span>stack.push(component.createIterator()); <span style="white-space:pre"> </span>return component; <span style="white-space:pre"> </span>} else { <span style="white-space:pre"> </span>return null; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>@Override <span style="white-space:pre"> </span>public void remove() { <span style="white-space:pre"> </span>throw new UnsupportedOperationException(); <span style="white-space:pre"> </span>} }
空迭代器:
public class NullIterator implements Iterator { @Override public boolean hasNext() { return false; } @Override public Object next() { return null; } @Override public void remove() { throw new UnsupportedOperationException(); } }
客户类(waitress):
public class Waitress { MenuComponent allMenus; public Waitress(MenuComponent allMenus) { this.allMenus = allMenus; } public void printMenu() { allMenus.print(); } public void printVegetarianMenu() { Iterator iterator = allMenus.createIterator(); System.out.println("\nVEGETARIAN MENU\n ----"); while (iterator.hasNext()) { MenuComponent menuComponent = (MenuComponent) iterator.next(); try { if (!menuComponent.isVegetarian()) { menuComponent.print(); } } catch (UnsupportedOperationException e) { } } } }
测试类:
public class MenuTestDrive { public static void main(String args[]){ MenuComponent pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU","BREAKFAST"); MenuComponent dinerMenu = new Menu("Diner MENU","LUNCH"); MenuComponent cafeMenu = new Menu("CAFE MENU","Dinner"); MenuComponent dessertMenu = new Menu("DESSERT MENU","Dessert of course!"); MenuComponent allMenus = new Menu("ALL MENUS","ALL menus combined"); allMenus.add(pancakeHouseMenu); allMenus.add(dinerMenu); allMenus.add(cafeMenu); dinerMenu.add(new MenuItem("Pasta", "Nice bread", true, 3.89)); dinerMenu.add(new MenuItem("Meat", "Nice meat", false, 3.89)); dinerMenu.add(new MenuItem("Chicken", "Nice Chicken", false, 13.89)); dinerMenu.add(dessertMenu); dessertMenu.add(new MenuItem("Apple Pie", "Nice apple pie", true, 1.59)); dessertMenu.add(new MenuItem("Fish", "Nice fish", false, 3.89)); dessertMenu.add(new MenuItem("Egg", "Nice egg", false, 1.89)); Waitress waitress = new Waitress(allMenus); // waitress.printMenu(); waitress.printVegetarianMenu(); } }
输出:VEGETARIAN MENU ---- Fish, 3.89 -- Nice fish Egg, 1.89 -- Nice egg
总结:
-- 组合模式提供一个结构,可同时包含个别对象和组合对象。
-- 组合模式允许客户对个别对象以及组合对象一视同仁。
-- 组合结构内的任意对象称为组件,组件可以是组合,也可以是叶节点。
-- 在实现组合模式时,有许多设计上的折衷。你要根据需要平衡透明性和安全性。