由於這系列篇幅較長,因此在這裏也不進行任何鋪墊,直奔主題去啦。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(); } }
結果這裏就不附上了,請你們自行去跑代碼實現吧。相信大家又對組合模式也已經有了一個大概了吧。下一篇,還有更犀利的,組合迭代器等着咱們。小編立刻回去搞起來,安排上。