迭代器模式:
提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
作用:
让我们游走于聚合内的每一个元素,而又不暴露其内部的表示。把游走的任务放在迭代器上,而不是聚合上。这样简化了聚合的接口和实现,也让责任各得其所。
组合模式:
要点:允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
- 迭代器允许访问聚合的元素,而不需要暴露它的内部结构。
- 迭代器将遍历聚合的工作封装进一个对象中。
- 当使用迭代器的时候,我们依赖聚合提供遍历。
- 迭代器提供了一个通用的接口,让我们遍历聚合的项,当我们编码使用聚合的项时,就可以使用多态机制。
- 我们应该努力让一个类只分配一个责任。
- 组合模式提供一个结构,可同时包容个别对象和组合对象。
- 组合模式允许客户对个别对象以及组合对象一视同仁。
- 组合结构内的任意对象称为组件,组件可以是组合,也可以是叶节点。
- 实现组合模式时,有许多设计上的折中。你要根据需要。
public abstract class MenuComponent { public void add(MenuComponent menuComponent){ throw new UnsupportedOperationException(); } public void remove(MenuComponent menuComponent){ throw new UnsupportedOperationException(); } public MenuComponent getChild(int i){ throw new UnsupportedOperationException(); } 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 print(){ throw new UnsupportedOperationException(); } public Iterator createIterator(){ throw new UnsupportedOperationException(); } }
/** * 菜单类 */ public class Menu extends MenuComponent{ ArrayList menuComponents = new ArrayList(); String name; String description; public Menu(String name, String description) { this.name = name; this.description = description; } public void add(MenuComponent menuComponent){ menuComponents.add(menuComponent); } public void remove(MenuComponent menuComponent){ menuComponents.remove(menuComponent); } public MenuComponent getChild(int i){ return (MenuComponent) menuComponents.get(i); } public String getName(){ return name; } public String getDescription(){ return description; } public void print(){ System.out.println("........."+getName()); System.out.println("........."+getDescription()); System.out.println("-------------------------------"); Iterator iterator = menuComponents.iterator(); while (iterator.hasNext()){ MenuComponent menuComponent = (MenuComponent) iterator.next(); menuComponent.print(); } } public Iterator createIterator(){ return new CompositeIterator(menuComponents.iterator()); } }
/** * 菜单项 */ 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 getDescription() { return description; } public boolean isVegetarian() { return vegetarian; } public double getPrice() { return price; } public void print(){ System.out.println("........."+getName()); if (isVegetarian()){ System.out.println("(v)"); } System.out.println(","+getPrice()); System.out.println(" --"+getDescription()); } public Iterator createIterator(){ return new NullIterator(); } }
public class CompositeIterator implements Iterator { Stack stack = new Stack(); public CompositeIterator(Iterator iterator) { stack.push(iterator); } public Object next(){ if (hasNext()){//当客户取下一个的时候,先调用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(); //我们就从堆栈的顶层中取出迭代器,看看是否还有下一个元素。如果它没有元素,我们将它弹出堆栈,然后递归地调用hasNext() if (!iterator.hasNext()){ stack.pop(); return hasNext(); }else {//表示还有下一个元素 return true; } } } public void remove(){ throw new UnsupportedOperationException(); } }
/** * 女招待 */ public class Waitress { MenuComponent allMemus; public Waitress(MenuComponent allMemus) { this.allMemus = allMemus; } public void printMenu(){ allMemus.print(); } public void printVegetarianMenu(){ Iterator iterator = allMemus.createIterator(); System.out.println("\nVEGETRAIAN MENU\n-----"); while (iterator.hasNext()){ MenuComponent menuComponent = (MenuComponent) iterator.next(); try { if (menuComponent.isVegetarian()){ menuComponent.print(); } }catch (UnsupportedOperationException e){ } } } }
public class NullIterator implements Iterator { public Object next(){ return null; } public boolean hasNext(){ return false; } public void remove(){ throw new UnsupportedOperationException(); } }
public class MenuTestDrive { public static void main(String[] args) { //创建所有的菜单对象 MenuComponent pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU","Breakfast"); MenuComponent denerMenu = 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(denerMenu); allMenus.add(cafeMenu); allMenus.add(dessertMenu); denerMenu.add(new MenuItem("素食BLT","(煎)培根、生菜&西红柿、面包",true,2.99)); denerMenu.add(new MenuItem("BLT","培根、生菜&西红柿",false,3.99)); denerMenu.add(new MenuItem("例汤","一碗例汤,配土豆沙拉",true,4.99)); denerMenu.add(new MenuItem("热狗","热狗、酸菜、上盖芝士",false,5.99)); denerMenu.add(new MenuItem("清蒸时蔬加糙米","清蒸时蔬加糙米",true,5.99)); denerMenu.add(dessertMenu); dessertMenu.add(new MenuItem("Apple Pie","Apple pie with a flakey crust,topped with vanilla ice cream",true,1.59)); pancakeHouseMenu.add(new MenuItem("K&B's薄煎饼早餐","薄煎饼、清蛋和土司",true,2.99)); pancakeHouseMenu.add(new MenuItem("薄煎饼早餐例餐","薄煎饼带煎蛋、香肠",false,4.99)); pancakeHouseMenu.add(new MenuItem("蓝莓薄煎饼","新鲜蓝莓和蓝莓糖浆做成的薄煎饼",true,1.99)); pancakeHouseMenu.add(new MenuItem("松饼","松饼、可以选择蓝莓或草莓",true,3.99)); cafeMenu.add(new MenuItem("摩卡咖啡","加糖的摩卡卡法",false,3.99)); cafeMenu.add(new MenuItem("卡布奇洛","加奶的卡布奇洛",false,4.99)); cafeMenu.add(new MenuItem("圣雪滴蓝","加巧克力的咖啡",false,5.23)); Waitress waitress = new Waitress(allMenus); waitress.printMenu(); } }