由于这系列篇幅较长,因此在这里也不进行任何铺垫,直奔主题去啦。java
咱们要如何在菜单上应用组合模式呢?一开始,咱们须要建立一个组件接口来做为菜单和菜单项的共同接口,让咱们可以用统一的作法来处理菜单和菜单项。换句话说,咱们能够针对菜单或菜单项调用相同的方法。ide
让咱们从头来看看如何让菜单可以符合组合模式的结构:oop
好了,咱们开始编写菜单组件的抽象类;请记住,菜单组件的角色是为叶节点和组合节点提供一个共同的接口。学习
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 abstract Iterator<MenuComponent> createIterator(); public void print() { throw new UnsupportedOperationException(); } }
让咱们来看菜单类。别忘了,这是组合类图里的叶类,它实现组合内元素的行为。测试
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 double getPrice() { return price; } public boolean isVegetarian() { return vegetarian; } public Iterator<MenuComponent> createIterator() { return new NullIterator(); } public void print() { System.out.print(" " + getName()); if (isVegetarian()) { System.out.print("(v)"); } System.out.println(", " + getPrice()); System.out.println(" -- " + getDescription()); } }
咱们已经有了菜单项,还须要组合类,这就是咱们叫作菜单的。别忘了,此组合类能够持有菜单项或其余菜单。优化
public class Menu extends MenuComponent { Iterator<MenuComponent> iterator = null; ArrayList<MenuComponent> menuComponents = new ArrayList<MenuComponent>(); 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 menuComponents.get(i); } public String getName() { return name; } public String getDescription() { return description; } public Iterator<MenuComponent> createIterator() { if (iterator == null) { iterator = new CompositeIterator(menuComponents.iterator()); } return iterator; } public void print() { System.out.print("\n" + getName()); System.out.println(", " + getDescription()); System.out.println("---------------------"); } }
由于菜单是一个组合,包含了菜单项和其余的菜单,因此它的print()应该打印出它所包含的一切。若是它不这么作,咱们就必须遍历整个组合的每一个节点,而后将每一项打印出来。这么一来,也就失去了使用组合结构的意义。this
因此,print还得进行优化,以下:设计
public void print() { System.out.print("\n" + getName()); System.out.println(", " + getDescription()); System.out.println("---------------------"); Iterator<MenuComponent> iterator = menuComponents.iterator(); while (iterator.hasNext()) { MenuComponent menuComponent = iterator.next(); menuComponent.print(); } }
看到上面了没,咱们用了迭代器。用它遍历全部菜单组件,遍历过程当中,可能遇到其余菜单,或者是遇到菜单项。因为菜单和菜单项都实现了print,那咱们只要调用print便可。code
开始测试数据以前,咱们了解一下,在运行时菜单组合是什么样的:blog
开始运行咱们的测试程序啦:
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); pancakeHouseMenu.add(new MenuItem( "K&B's Pancake Breakfast", "Pancakes with scrambled eggs, and toast", true, 2.99)); pancakeHouseMenu.add(new MenuItem( "Regular Pancake Breakfast", "Pancakes with fried eggs, sausage", false, 2.99)); pancakeHouseMenu.add(new MenuItem( "Blueberry Pancakes", "Pancakes made with fresh blueberries, and blueberry syrup", true, 3.49)); pancakeHouseMenu.add(new MenuItem( "Waffles", "Waffles, with your choice of blueberries or strawberries", true, 3.59)); dinerMenu.add(new MenuItem( "Vegetarian BLT", "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 2.99)); dinerMenu.add(new MenuItem( "BLT", "Bacon with lettuce & tomato on whole wheat", false, 2.99)); dinerMenu.add(new MenuItem( "Soup of the day", "A bowl of the soup of the day, with a side of potato salad", false, 3.29)); dinerMenu.add(new MenuItem( "Hotdog", "A hot dog, with saurkraut, relish, onions, topped with cheese", false, 3.05)); dinerMenu.add(new MenuItem( "Steamed Veggies and Brown Rice", "A medly of steamed vegetables over brown rice", true, 3.99)); dinerMenu.add(new MenuItem( "Pasta", "Spaghetti with Marinara Sauce, and a slice of sourdough bread", true, 3.89)); dinerMenu.add(dessertMenu); dessertMenu.add(new MenuItem( "Apple Pie", "Apple pie with a flakey crust, topped with vanilla icecream", true, 1.59)); dessertMenu.add(new MenuItem( "Cheesecake", "Creamy New York cheesecake, with a chocolate graham crust", true, 1.99)); dessertMenu.add(new MenuItem( "Sorbet", "A scoop of raspberry and a scoop of lime", true, 1.89)); cafeMenu.add(new MenuItem( "Veggie Burger and Air Fries", "Veggie burger on a whole wheat bun, lettuce, tomato, and fries", true, 3.99)); cafeMenu.add(new MenuItem( "Soup of the day", "A cup of the soup of the day, with a side salad", false, 3.69)); cafeMenu.add(new MenuItem( "Burrito", "A large burrito, with whole pinto beans, salsa, guacamole", true, 4.29)); Waitress waitress = new Waitress(allMenus); waitress.printVegetarianMenu(); } }
结果这里就不附上了,请你们自行去跑代码实现吧。相信大家又对组合模式也已经有了一个大概了吧。下一篇,还有更犀利的,组合迭代器等着咱们。小编立刻回去搞起来,安排上。