设计模式目录:
概述:
第1部分 问题引入以及定义
先来看下符合我们需求的结构图:
组合模式允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象的组合。
下面看看让菜单能够符合组合模式的结构:
第2部分 代码实现
好了,下面开始编写菜单组合件的抽象类,请记住,菜单组合件的角色是为叶节点和组合节点提供一个共同的接口。
1 package firsthead.composite; 2 3 /** 4 * 菜单组件 5 * @ClassName: MenuComponent 6 * 7 * @author Xingle 8 * @date 2014-8-4 下午2:50:19 9 */ 10 public abstract class MenuComponent { 11 12 /*因为有些方法只对菜单项有意义,而有些则只对菜单有意义,默认实现是抛出UnsupportedOperationException异常。 13 * 这样,如果菜单项或者菜单不支持某个操作,他们就不需要做任何事情,直接继承默认实现就可以了。*/ 14 15 //组合的方法组织在一起,即新增、删除和取得菜单组件 16 public void add(MenuComponent menuComponent){ 17 throw new UnsupportedOperationException(); 18 } 19 20 public MenuComponent getChild(int i){ 21 throw new UnsupportedOperationException(); 22 } 23 24 public void remove(MenuComponent menuComponent) { 25 throw new UnsupportedOperationException(); 26 } 27 28 //下面是操作的方法 29 public String getName(){ 30 throw new UnsupportedOperationException(); 31 } 32 33 public String getDescription() { 34 throw new UnsupportedOperationException(); 35 } 36 public double getPrice() { 37 throw new UnsupportedOperationException(); 38 } 39 public boolean isVegetarian() { 40 throw new UnsupportedOperationException(); 41 } 42 43 public void print() { 44 throw new UnsupportedOperationException(); 45 } 46 }
实现菜单项:
1 package firsthead.composite; 2 3 /** 4 * 菜单项 5 * @ClassName: MenuItem 6 * TODO 7 * @author Xingle 8 * @date 2014-8-4 下午2:57:20 9 */ 10 public class MenuItem extends MenuComponent{ 11 String name; 12 String description; 13 boolean vegetarian; 14 double price; 15 16 public MenuItem(String name, String description, boolean vegetarian, double price){ 17 this.name = name; 18 this.description = description; 19 this.vegetarian = vegetarian; 20 this.price = price; 21 } 22 23 public String getName() { 24 return name; 25 } 26 27 public String getDescription() { 28 return description; 29 } 30 31 public boolean isVegetarian() { 32 return vegetarian; 33 } 34 35 public double getPrice() { 36 return price; 37 } 38 39 public void print(){ 40 System.out.println(" "+getName()); 41 if(isVegetarian()){ 42 System.out.print("(v)"); 43 } 44 System.out.println(", "+getPrice()); 45 System.out.println(" -- " + getDescription()); 46 } 47 48 }
实现组合菜单:
1 package firsthead.composite; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 6 /** 7 * 菜单 8 * @ClassName: Menu 9 * TODO 10 * @author Xingle 11 * @date 2014-8-4 下午3:02:15 12 */ 13 public class Menu extends MenuComponent{ 14 //菜单可以有任意数目的孩子,这些孩子都必须属于MenuComponent类型,我们使用内部的ArrayList记录它们 15 ArrayList menuComponents = new ArrayList(); 16 String name; 17 String description; 18 19 public Menu(String name,String description){ 20 this.name = name; 21 this.description = description; 22 } 23 24 //将菜单项和其他菜单加入菜单中,同理,处理删除或者取得某个MenuComponent 25 public void add(MenuComponent menuComponent){ 26 menuComponents.add(menuComponent); 27 } 28 29 public void remove(MenuComponent menuComponent){ 30 menuComponents.remove(menuComponent); 31 } 32 33 public MenuComponent getChild(int i){ 34 return (MenuComponent) menuComponents.get(i); 35 } 36 37 public String getName() { 38 return name; 39 } 40 41 public String getDescription() { 42 return description; 43 } 44 45 //注意,这里没有覆盖getPrice()或者isVegetarian(),因为这些方法对Menu来说并没有意义 46 47 public void print(){ 48 System.out.print(" " + getName()); 49 System.out.println(", " + getDescription()); 50 System.out.println("---------------------"); 51 52 //不仅打印出菜单本身的信息,也打印出菜单内所有组件的内容:其他菜单和菜单项 53 Iterator iterator = menuComponents.iterator(); 54 while(iterator.hasNext()){ 55 MenuComponent menuComponent = (MenuComponent)iterator.next(); 56 menuComponent.print(); 57 } 58 } 59 }
女招待代码:
1 package firsthead.composite; 2 3 /** 4 * 女招待 5 * @ClassName: Waitress 6 * TODO 7 * @author Xingle 8 * @date 2014-8-4 下午3:18:33 9 */ 10 public class Waitress { 11 MenuComponent allMenus; 12 13 //只要将最顶层的菜单组件交给女招待就可以了 14 public Waitress(MenuComponent allMenus){ 15 this.allMenus = allMenus; 16 } 17 18 public void print(){ 19 allMenus.print(); 20 } 21 22 }
测试程序:
1 package firsthead.composite; 2 3 /** 4 * 组合模式测试程序 5 * 6 * @ClassName: MenuTestDrive TODO 7 * @author Xingle 8 * @date 2014-8-4 下午3:22:43 9 */ 10 public class MenuTestDrive { 11 12 public static void main(String[] args) { 13 MenuComponent pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU", 14 "早餐 Breakfast"); 15 MenuComponent dinerMenu = new Menu("DINER MENU", "午餐 Lunch"); 16 MenuComponent cafeMenu = new Menu("CAFE MENU", "晚餐 Dinner"); 17 MenuComponent dessertMenu = new Menu("DESSERT MENU", 18 " Dessert of course!"); 19 MenuComponent coffeeMenu = new Menu("COFFEE MENU", 20 "Stuff to go with your afternoon coffee"); 21 22 // 最顶层菜单 23 MenuComponent allMenus = new Menu("ALL MENUS", "All menus combined"); 24 25 // 将每个菜单加入allMenus中 26 allMenus.add(pancakeHouseMenu); 27 allMenus.add(dinerMenu); 28 allMenus.add(cafeMenu); 29 30 // pancakeHouseMenu 加入具体菜单项 31 pancakeHouseMenu.add(new MenuItem("K&B's Pancake Breakfast", 32 "Pancakes with scrambled eggs, and toast", true, 2.99)); 33 pancakeHouseMenu.add(new MenuItem("Regular Pancake Breakfast", 34 "Pancakes with fried eggs, sausage", false, 2.99)); 35 pancakeHouseMenu.add(new MenuItem("Blueberry Pancakes", 36 "Pancakes made with fresh blueberries, and blueberry syrup", 37 true, 3.49)); 38 pancakeHouseMenu.add(new MenuItem("Waffles", 39 "Waffles, with your choice of blueberries or strawberries", 40 true, 3.59)); 41 42 //dinerMenu 加入具体菜单项 43 dinerMenu.add(new MenuItem("Vegetarian BLT", 44 "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 45 2.99)); 46 dinerMenu.add(new MenuItem("BLT", 47 "Bacon with lettuce & tomato on whole wheat", false, 2.99)); 48 49 // 50 dinerMenu.add(dessertMenu); 51 52 dessertMenu.add(new MenuItem("Apple Pie", 53 "Apple pie with a flakey crust, topped with vanilla icecream", 54 true, 1.59)); 55 56 dessertMenu.add(new MenuItem("Cheesecake", 57 "Creamy New York cheesecake, with a chocolate graham crust", 58 true, 1.99)); 59 dessertMenu.add(new MenuItem("Sorbet", 60 "A scoop of raspberry and a scoop of lime", true, 1.89)); 61 62 //cafeMenu 加入具体菜单项 63 cafeMenu.add(new MenuItem( 64 "Veggie Burger and Air Fries", 65 "Veggie burger on a whole wheat bun, lettuce, tomato, and fries", 66 true, 3.99)); 67 cafeMenu.add(new MenuItem("Soup of the day", 68 "A cup of the soup of the day, with a side salad", false, 3.69)); 69 70 cafeMenu.add(coffeeMenu); 71 72 coffeeMenu 73 .add(new MenuItem( 74 "Veggie Burger and Air Fries", 75 "Veggie burger on a whole wheat bun, lettuce, tomato, and fries", 76 true, 3.99)); 77 coffeeMenu.add(new MenuItem("Bagel", 78 "Flavors include sesame, poppyseed, cinnamon raisin, pumpkin", 79 false, 0.69)); 80 81 Waitress waitress = new Waitress(allMenus); 82 waitress.print(); 83 } 84 85 }
执行结果:
ALL MENUS, All menus combined
---------------------
PANCAKE HOUSE MENU, 早餐 Breakfast
---------------------
K&B's Pancake Breakfast
(v), 2.99
-- Pancakes with scrambled eggs, and toast
Regular Pancake Breakfast
, 2.99
-- Pancakes with fried eggs, sausage
Blueberry Pancakes
(v), 3.49
-- Pancakes made with fresh blueberries, and blueberry syrup
Waffles
(v), 3.59
-- Waffles, with your choice of blueberries or strawberries
DINER MENU, 午餐 Lunch
---------------------
Vegetarian BLT
(v), 2.99
-- (Fakin') Bacon with lettuce & tomato on whole wheat
BLT
, 2.99
-- Bacon with lettuce & tomato on whole wheat
DESSERT MENU, Dessert of course!
---------------------
Apple Pie
(v), 1.59
-- Apple pie with a flakey crust, topped with vanilla icecream
Cheesecake
(v), 1.99
-- Creamy New York cheesecake, with a chocolate graham crust
Sorbet
(v), 1.89
-- A scoop of raspberry and a scoop of lime
CAFE MENU, 晚餐 Dinner
---------------------
Veggie Burger and Air Fries
(v), 3.99
-- Veggie burger on a whole wheat bun, lettuce, tomato, and fries
Soup of the day
, 3.69
-- A cup of the soup of the day, with a side salad
COFFEE MENU, Stuff to go with your afternoon coffee
---------------------
Veggie Burger and Air Fries
(v), 3.99
-- Veggie burger on a whole wheat bun, lettuce, tomato, and fries
Bagel
, 0.69
-- Flavors include sesame, poppyseed, cinnamon raisin, pumpkin
第3部分 用组合来使用迭代器
想要实现一个组合迭代器,我们为每个组件都加上createIterator()方法。先从抽象的MenuComponent类开始。
1 package firsthead.composite; 2 3 import java.util.Iterator; 4 5 /** 6 * 菜单组件 7 * @ClassName: MenuComponent 8 * 9 * @author Xingle 10 * @date 2014-8-4 下午2:50:19 11 */ 12 public abstract class MenuComponent { 13 14 /*因为有些方法只对菜单项有意义,而有些则只对菜单有意义,默认实现是抛出UnsupportedOperationException异常。 15 * 这样,如果菜单项或者菜单不支持某个操作,他们就不需要做任何事情,直接继承默认实现就可以了。*/ 16 17 //组合的方法组织在一起,即新增、删除和取得菜单组件 18 public void add(MenuComponent menuComponent){ 19 throw new UnsupportedOperationException(); 20 } 21 22 public MenuComponent getChild(int i){ 23 throw new UnsupportedOperationException(); 24 } 25 26 public void remove(MenuComponent menuComponent) { 27 throw new UnsupportedOperationException(); 28 } 29 30 //下面是操作的方法 31 public String getName(){ 32 throw new UnsupportedOperationException(); 33 } 34 35 public String getDescription() { 36 throw new UnsupportedOperationException(); 37 } 38 public double getPrice() { 39 throw new UnsupportedOperationException(); 40 } 41 public boolean isVegetarian() { 42 throw new UnsupportedOperationException(); 43 } 44 45 public void print() { 46 throw new UnsupportedOperationException(); 47 } 48 49 //加入一个方法,每个菜单和菜单项都必须实现这个方法,即,对每一个组合调用createIterator()方法,将会应用于该组合的所有孩子 50 public abstract Iterator createIterator(); 51 }
修改菜单项和菜单组件的代码:
1 package firsthead.composite; 2 3 import java.util.ArrayList; 4 import java.util.Iterator; 5 6 /** 7 * 菜单 8 * @ClassName: Menu 9 * TODO 10 * @author Xingle 11 * @date 2014-8-4 下午3:02:15 12 */ 13 public class Menu extends MenuComponent{ 14 //菜单可以有任意数目的孩子,这些孩子都必须属于MenuComponent类型,我们使用内部的ArrayList记录它们 15 ArrayList menuComponents = new ArrayList(); 16 String name; 17 String description; 18 19 public Menu(String name,String description){ 20 this.name = name; 21 this.description = description; 22 } 23 24 //将菜单项和其他菜单加入菜单中,同理,处理删除或者取得某个MenuComponent 25 public void add(MenuComponent menuComponent){ 26 menuComponents.add(menuComponent); 27 } 28 29 public void remove(MenuComponent menuComponent){ 30 menuComponents.remove(menuComponent); 31 } 32 33 public MenuComponent getChild(int i){ 34 return (MenuComponent) menuComponents.get(i); 35 } 36 37 public String getName() { 38 return name; 39 } 40 41 public String getDescription() { 42 return description; 43 } 44 45 //注意,这里没有覆盖getPrice()或者isVegetarian(),因为这些方法对Menu来说并没有意义 46 47 public void print(){ 48 System.out.print(" " + getName()); 49 System.out.println(", " + getDescription()); 50 System.out.println("---------------------"); 51 52 //不仅打印出菜单本身的信息,也打印出菜单内所有组件的内容:其他菜单和菜单项 53 Iterator iterator = menuComponents.iterator(); 54 while(iterator.hasNext()){ 55 MenuComponent menuComponent = (MenuComponent)iterator.next(); 56 menuComponent.print(); 57 } 58 } 59 60 /** 61 * 62 * @Description: 63 * @return 64 * @author xingle 65 * @data 2014-8-4 下午4:39:12 66 */ 67 @Override 68 public Iterator createIterator() { 69 //组合迭代器 70 return new CompositeIterator(menuComponents.iterator()); 71 } 72 }
1 package firsthead.composite; 2 3 import java.util.Iterator; 4 5 /** 6 * 菜单项 7 * @ClassName: MenuItem 8 * TODO 9 * @author Xingle 10 * @date 2014-8-4 下午2:57:20 11 */ 12 public class MenuItem extends MenuComponent{ 13 String name; 14 String description; 15 boolean vegetarian; 16 double price; 17 18 public MenuItem(String name, String description, boolean vegetarian, double price){ 19 this.name = name; 20 this.description = description; 21 this.vegetarian = vegetarian; 22 this.price = price; 23 } 24 25 public String getName() { 26 return name; 27 } 28 29 public String getDescription() { 30 return description; 31 } 32 33 public boolean isVegetarian() { 34 return vegetarian; 35 } 36 37 public double getPrice() { 38 return price; 39 } 40 41 public void print(){ 42 System.out.println(" "+getName()); 43 if(isVegetarian()){ 44 System.out.print("(v)"); 45 } 46 System.out.println(", "+getPrice()); 47 System.out.println(" -- " + getDescription()); 48 } 49 50 /** 51 * 52 * @Description: TODO 53 * @return 54 * @author xingle 55 * @data 2014-8-4 下午4:39:17 56 */ 57 @Override 58 public Iterator createIterator() { 59 return new NullIterator(); 60 } 61 62 }
其中,菜单的组合迭代器代码,这部分代码多研读:
1 package firsthead.composite; 2 3 import java.util.Iterator; 4 import java.util.Stack; 5 6 /** 7 * 组合迭代器 8 * @ClassName: CompositeIterator 9 * TODO 10 * @author Xingle 11 * @date 2014-8-4 下午4:41:49 12 */ 13 public class CompositeIterator implements Iterator{ 14 15 Stack stack = new Stack(); 16 17 //将要遍历的顶层组合的迭代器传入,放入一个堆栈数据结构中 18 public CompositeIterator(Iterator iterator){ 19 stack.push(iterator); 20 } 21 22 /** 23 * 24 * @Description: TODO 25 * @return 26 * @author xingle 27 * @data 2014-8-4 下午4:42:46 28 */ 29 @Override 30 public boolean hasNext() { 31 //检查堆栈是否被清空,如果已经空了,就表示没有下一元素了 32 if(stack.empty()){ 33 return false; 34 } 35 else{ 36 //否则,从堆栈的顶层中取出迭代器,看看是否还有下一元素。如果它没有元素,将它弹出堆栈,然后递归地调用hasNext()。 37 Iterator Iterator = (java.util.Iterator) stack.peek(); 38 if(!Iterator.hasNext()){ 39 stack.pop(); 40 return hasNext(); 41 }else{ 42 return true; 43 } 44 } 45 } 46 47 /** 48 * 49 * @Description: TODO 50 * @return 51 * @author xingle 52 * @data 2014-8-4 下午4:42:46 53 */ 54 @Override 55 public Object next() { 56 //当客户想要取得下一个元素的时候,先调用hasNext()来确定是否还有下一个 57 if(hasNext()){ 58 //如果还有下一个元素,就从堆栈中取出目前的迭代器,然后取得它的下一个元素 59 Iterator iterator = (Iterator) stack.peek(); 60 MenuComponent component = (MenuComponent) iterator.next(); 61 //如果元素是一个菜单,就有了另一个需要被包含进遍历的组合,放进堆栈中。 不管是不是菜单,都返回该组件。 62 if(component instanceof Menu){ 63 stack.push(component.createIterator()); 64 } 65 return component; 66 }else { 67 return null; 68 } 69 } 70 71 /** 72 * 不支持删除,这里只有遍历 73 * @Description: TODO 74 * @author xingle 75 * @data 2014-8-4 下午4:42:46 76 */ 77 @Override 78 public void remove() { 79 throw new UnsupportedOperationException(); 80 81 } 82 83 }
菜单组件的NullIterator,空迭代器,指项目内没有可以遍历的:
1 package firsthead.composite; 2 3 import java.util.Iterator; 4 5 /** 6 * 空迭代器 7 * @ClassName: NullIterator 8 * 9 * @author Xingle 10 * @date 2014-8-4 下午5:05:25 11 */ 12 public class NullIterator implements Iterator{ 13 14 /** 15 * 16 * @Description: TODO 17 * @return 18 * @author xingle 19 * @data 2014-8-4 下午5:05:47 20 */ 21 @Override 22 public boolean hasNext() { 23 return false; 24 } 25 26 /** 27 * 28 * @Description: TODO 29 * @return 30 * @author xingle 31 * @data 2014-8-4 下午5:05:47 32 */ 33 @Override 34 public Object next() { 35 return null; 36 } 37 38 /** 39 * 40 * @Description: TODO 41 * @author xingle 42 * @data 2014-8-4 下午5:05:47 43 */ 44 @Override 45 public void remove() { 46 throw new UnsupportedOperationException(); 47 48 } 49 50 }
女招待,增加打印蔬菜的方法printVegetarianMenu():
1 package firsthead.composite; 2 3 import java.util.Iterator; 4 5 /** 6 * 女招待 7 * @ClassName: Waitress 8 * TODO 9 * @author Xingle 10 * @date 2014-8-4 下午3:18:33 11 */ 12 public class Waitress { 13 MenuComponent allMenus; 14 15 //只要将最顶层的菜单组件交给女招待就可以了 16 public Waitress(MenuComponent allMenus){ 17 this.allMenus = allMenus; 18 } 19 20 public void print(){ 21 allMenus.print(); 22 } 23 24 public void printVegetarianMenu(){ 25 Iterator iterator = allMenus.createIterator(); 26 while(iterator.hasNext()){ 27 MenuComponent menucomponent = (MenuComponent) iterator.next(); 28 try{//调用全部的menucomponent的isVegetarian()方法,但是Menu会抛出异常,因为它们不支持这个操作 29 if(menucomponent.isVegetarian()){ 30 menucomponent.print(); 31 } 32 }catch(UnsupportedOperationException e){ 33 } 34 35 } 36 } 37 38 }
测试程序:
1 package firsthead.composite; 2 3 /** 4 * 组合模式测试程序 5 * 6 * @ClassName: MenuTestDrive 7 * @author Xingle 8 * @date 2014-8-4 下午3:22:43 9 */ 10 public class MenuTestDrive { 11 12 public static void main(String[] args) { 13 MenuComponent pancakeHouseMenu = new Menu("PANCAKE HOUSE MENU", 14 "早餐 Breakfast"); 15 MenuComponent dinerMenu = new Menu("DINER MENU", "午餐 Lunch"); 16 MenuComponent cafeMenu = new Menu("CAFE MENU", "晚餐 Dinner"); 17 MenuComponent dessertMenu = new Menu("DESSERT MENU", 18 " Dessert of course!"); 19 MenuComponent coffeeMenu = new Menu("COFFEE MENU", 20 "Stuff to go with your afternoon coffee"); 21 22 // 最顶层菜单 23 MenuComponent allMenus = new Menu("ALL MENUS", "All menus combined"); 24 25 // 将每个菜单加入allMenus中 26 allMenus.add(pancakeHouseMenu); 27 allMenus.add(dinerMenu); 28 allMenus.add(cafeMenu); 29 30 // pancakeHouseMenu 加入具体菜单项 31 pancakeHouseMenu.add(new MenuItem("K&B's Pancake Breakfast", 32 "Pancakes with scrambled eggs, and toast", true, 2.99)); 33 pancakeHouseMenu.add(new MenuItem("Regular Pancake Breakfast", 34 "Pancakes with fried eggs, sausage", false, 2.99)); 35 pancakeHouseMenu.add(new MenuItem("Blueberry Pancakes", 36 "Pancakes made with fresh blueberries, and blueberry syrup", 37 true, 3.49)); 38 pancakeHouseMenu.add(new MenuItem("Waffles", 39 "Waffles, with your choice of blueberries or strawberries", 40 true, 3.59)); 41 42 //dinerMenu 加入具体菜单项 43 dinerMenu.add(new MenuItem("Vegetarian BLT", 44 "(Fakin') Bacon with lettuce & tomato on whole wheat", true, 45 2.99)); 46 dinerMenu.add(new MenuItem("BLT", 47 "Bacon with lettuce & tomato on whole wheat", false, 2.99)); 48 49 // 50 dinerMenu.add(dessertMenu); 51 52 dessertMenu.add(new MenuItem("Apple Pie", 53 "Apple pie with a flakey crust, topped with vanilla icecream", 54 true, 1.59)); 55 56 dessertMenu.add(new MenuItem("Cheesecake", 57 "Creamy New York cheesecake, with a chocolate graham crust", 58 true, 1.99)); 59 dessertMenu.add(new MenuItem("Sorbet", 60 "A scoop of raspberry and a scoop of lime", true, 1.89)); 61 62 //cafeMenu 加入具体菜单项 63 cafeMenu.add(new MenuItem( 64 "Veggie Burger and Air Fries", 65 "Veggie burger on a whole wheat bun, lettuce, tomato, and fries", 66 true, 3.99)); 67 cafeMenu.add(new MenuItem("Soup of the day", 68 "A cup of the soup of the day, with a side salad", false, 3.69)); 69 70 cafeMenu.add(coffeeMenu); 71 72 coffeeMenu 73 .add(new MenuItem( 74 "Veggie Burger and Air Fries", 75 "Veggie burger on a whole wheat bun, lettuce, tomato, and fries", 76 true, 3.99)); 77 coffeeMenu.add(new MenuItem("Bagel", 78 "Flavors include sesame, poppyseed, cinnamon raisin, pumpkin", 79 false, 0.69)); 80 81 Waitress waitress = new Waitress(allMenus); 82 //waitress.print(); 83 waitress.printVegetarianMenu(); 84 } 85 86 }
执行结果:
K&B's Pancake Breakfast
(v), 2.99
-- Pancakes with scrambled eggs, and toast
Blueberry Pancakes
(v), 3.49
-- Pancakes made with fresh blueberries, and blueberry syrup
Waffles
(v), 3.59
-- Waffles, with your choice of blueberries or strawberries
Vegetarian BLT
(v), 2.99
-- (Fakin') Bacon with lettuce & tomato on whole wheat
Apple Pie
(v), 1.59
-- Apple pie with a flakey crust, topped with vanilla icecream
Cheesecake
(v), 1.99
-- Creamy New York cheesecake, with a chocolate graham crust
Sorbet
(v), 1.89
-- A scoop of raspberry and a scoop of lime
Apple Pie
(v), 1.59
-- Apple pie with a flakey crust, topped with vanilla icecream
Cheesecake
(v), 1.99
-- Creamy New York cheesecake, with a chocolate graham crust
Sorbet
(v), 1.89
-- A scoop of raspberry and a scoop of lime
Veggie Burger and Air Fries
(v), 3.99
-- Veggie burger on a whole wheat bun, lettuce, tomato, and fries
Veggie Burger and Air Fries
(v), 3.99
-- Veggie burger on a whole wheat bun, lettuce, tomato, and fries
Veggie Burger and Air Fries
(v), 3.99
-- Veggie burger on a whole wheat bun, lettuce, tomato, and fries
看下女招待打印蔬菜菜单的方法中,一般来说,try/catch是一种错误处理的方法,而不是程序逻辑的方法。如果不这么做,还有哪些选择呢?我们可以在调用isVegetarian()方法之前,用instanceof来检查菜单组件的运行类型,以确定它是菜单项。但是这么做,我们就会因为无法统一菜单和菜单项而失去透明性。
我们也可以改写Menu的isVegetarian()方法,让它返回false,这提供了一个简单的解决方案,同时也保持了透明性。
我们的解决方案是为了要清楚的表示我们的想法。我们真正想要传达的是:isVegetarian()是Menu没有支持的操作(这和说isVegetarian()是false意义不等同)。这样的做法也允许以后去为Menu实现一个合理的isVegetarian()方法,而我们不必为此再修改这里的代码了。