设计模式 4 —— 迭代器和组合模式(组合)

设计模式目录:

设计模式 1 ——观察者模式

设计模式 2 —— 装饰者模式 

设计模式 3 —— 迭代器和组合模式(迭代器)

设计模式 4 —— 迭代器和组合模式(组合)

设计模式 5 —— 工厂模式

设计模式 6 —— 单件模式

设计模式 7 —— 命令模式

设计模式 8 —— 适配器和外观模式

设计模式 9 —— 模板方法模式

设计模式 10 —— 状态模式

参考

概述:

第1部分 问题引入以及定义

第2部分 实现代码

第3部分 用组合来使用迭代器

第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()方法,而我们不必为此再修改这里的代码了。


参考:

  1. [Head First设计模式]生活中学设计模式——组合模式

原文地址:https://www.cnblogs.com/xingele0917/p/3890070.html