首先,我们有三个类,分别代表“菜单项”,“对象村餐厅菜单”和“对象村煎饼屋菜单”。
菜单类:
package com.hufei.learnDesignPattern; public class MenuItem { 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 this.name; } public String getDescription() { return description; } public boolean isVegetarian() { return vegetarian; } public double getPrice() { return price; } }
对象村煎饼屋菜单:
package com.hufei.learnDesignPattern; import java.util.ArrayList; /** * the menu of a pancake house * */ public class PancakeHouseMenu { ArrayList menuItems; public PancakeHouseMenu(){ menuItems = new ArrayList(); addItem("K&B's Pancake Breakfast", "Pancakes with scrambled egges, and toast", true, 2.99); addItem("Regular Pancake Breakfast", "Pancakes with fried eggs, sausage", false, 2.99); addItem("Buleberry Pancakes", "Pancakes made with fresh blueberries", true, 3.49); addItem("Waffles", "Waffles, with your choice of blueberries or strawberries", true, 3.59d); } //向菜单中加入一个子项 public void addItem(String name,String description, boolean vegetarian, double price){ MenuItem menuItem = new MenuItem(name,description,vegetarian,price); this.menuItems.add(menuItem); } public ArrayList getMenuItems(){ return this.menuItems; } }
对象村餐厅菜单:
package com.hufei.learnDesignPattern; public class DinerMenu { static final int MAX_ITEMS = 6; int numberOfItems = 0; MenuItem[] menuItems; public DinerMenu(){ menuItems = new MenuItem[MAX_ITEMS]; } public void addItem(String name ,String description, boolean vegetarian, double price){ MenuItem menuItem = new MenuItem(name,description,vegetarian,price); if(numberOfItems >= MAX_ITEMS){ System.err.println("Sorry, menu is full! Can't add item to menu"); } else{ menuItems[numberOfItems] = menuItem; numberOfItems = numberOfItems +1 ; } } public MenuItem[] getMenuItems(){ return this.menuItems; } //还有菜单的其他方法 }
由于对象村餐厅和煎饼屋合并后,煎饼屋提供早餐,而餐厅提供午餐。需要一个女招待Alice。
Alice 的工作如下:
printMenu()
--打印出菜单上的每一项
printBreakfastMenu()
--只打印早餐项
printLunchMenu()
--只打印午餐项
printVegetarianMenu()
--打印所有的素食菜单项
isItemVegetarian(name)
--制定项的名称,如果是素食的话,返回true,否则返回false
以下是我们女招待的实现类:
package com.hufei.learnDesignPattern; import java.util.ArrayList; //第一版的女招待 public class Waitress_1ed { public void printMenu(){ PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu(); ArrayList breakfastItems = pancakeHouseMenu.getMenuItems(); DinerMenu dinerMenu = new DinerMenu(); MenuItem[] lunchItems = dinerMenu.getMenuItems(); for(int i = 0; i < breakfastItems.size(); i++){ MenuItem item = (MenuItem)breakfastItems.get(i); System.out.println(item.getName()+" "); System.out.println(item.getDescription()+" "); System.out.println(item.getPrice()); } for(MenuItem item: lunchItems){ System.out.println(item.getName()+" "); System.out.println(item.getDescription()+" "); System.out.println(item.getPrice()); } } }
在该类只实现了printMenu方法,其他方法与printMenu方法类似,都要循环遍历两个菜单项。如果,还有第三家餐厅合并,就需要三个循环遍历。
printMenu()的实现,会有以下几个问题:
- 针对接口编程,而非针对实现编程。printMenu()的实现是针对PancakeHouseMenu和DinerMenu的具体代码实现编码。
- 如果我们还有另一种菜单项用Hashtable来存放,我们会因此需要修改女招待中的许多代码。
- 女招待需要知道每个菜单如何表达内部的菜单项集合,这违背了封装。
- 重复代码比较多,printMenu()方法中需要两个循环,来遍历两种不同的菜单。如果还有第三种菜单,我们就需要第三个循环。
对此,我们应该如何处理呢?