〇、小故事
在一座小镇上,有两家特别有名气的小店,一家是远近闻名的早餐店,它家的早餐特别好吃,每天早上都能排起长长的队伍;另一家是个蛋糕店,他家是专门从法国请来的蛋糕师傅,蛋糕的香味真是香飘万里。
自从听说这个酱香拿铁销量非常高之后,这两家店的老板们就觉得强强联合才是能让小店更进一步的关键,所以,两家老板打算合并起来一起做生意。
但是呢,早餐店的菜单是ArrayList维护的,蛋糕店的菜单是数组维护的。那么对于服务员来说,他报菜单的时候,既要针对ArrayList
类型的菜单进行遍历输出菜品,又需要再针对数组
进行遍历输出菜品。并且,如果后面合并的小店越来越多,菜单用了其他的数据结构存储怎么办呢? 如果强制所有的饭店都使用统一的集合类型去存储菜单的话,那么对小店来说,所有用到旧菜单的地方都需要代码修改。这样改动太大了呀。
为了解决这个问题,我们统一提供了迭代器接口,每个饭店的菜单都要实现迭代器这个接口。那么这就是今天要给大家介绍的设计模式——迭代器模式。
一、模式定义
迭代器模式(Iterator Pattern
)
提供一个方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
二、模式类图
针对上面两个小店合并后菜单类型不一致导致的遍历问题,我们来看一下如何采用迭代模式来解决。首先,我们要创建菜单接口类Menu,以及两个饭店的菜单实现类,分别是:ARestaurantMenu和BRestaurantMenu。其次,创建菜单迭代器接口MenuIterator和两个饭店的菜单迭代器实现类,分别是:ARestaurantMenuIterator和BRestaurantMenuIterator。最后,创建服务员类Waitress和菜单项类MenuItem。具体类图请见如下所示:
三、代码实现
创建菜单明细项:MenuItem.java
public class MenuItem { // 菜名 private String name; // 菜品详细介绍 private String desc; // 是否是素食 private boolean vegetarian; // 菜的价格 private double price; public MenuItem(String name, String desc, boolean vegetarian, double price) { this.name = name; this.desc = desc; this.vegetarian = vegetarian; this.price = price; } /** xxxGet()和xxxSet()方法*/ }
创建小店菜单接口:Menu.java
public interface Menu { MenuIterator iterator(); // 获得迭代器 }
创建A饭店菜单实现类:ARestaurantMenu.java
public class ARestaurantMenu implements Menu { private ArrayList<MenuItem> menuItems; public ARestaurantMenu() { menuItems = new ArrayList<>(); addItem("油条", "油条的描述", true, 0.5); addItem("豆浆", "豆浆的描述", true, 1.9); addItem("茶叶蛋", "茶叶蛋的描述", true, 1.5); addItem("小笼包", "小笼包的描述", true, 2.1); } private void addItem(String name, String desc, boolean vegetarian, double price) { MenuItem menuItem = new MenuItem(name, desc, vegetarian, price); menuItems.add(menuItem); } public ArrayList<MenuItem> getMenuItems() { return menuItems; } @Override public MenuIterator iterator() { return new ARestaurantMenuIterator(menuItems); } }
创建B饭店菜单实现类:BRestaurantMenu.java
public class BRestaurantMenu implements Menu { int nums = 0; private static final int MAX_SIZE = 5; // 餐厅老板很有个性,只做5道菜 private MenuItem[] menuItems; public BRestaurantMenu() { menuItems = new MenuItem[MAX_SIZE]; addItem("宫保鸡丁", "宫保鸡丁的描述", true, 0.5); addItem("北京烤鸭", "北京烤鸭的描述", true, 1.9); addItem("黄焖鸡米饭", "黄焖鸡米饭的描述", true, 1.5); addItem("啵啵鱼", "啵啵鱼的描述", true, 2.1); addItem("兰州拉面", "兰州拉面的描述", true, 2.1); } private void addItem(String name, String desc, boolean vegetarian, double price) { MenuItem menuItem = new MenuItem(name, desc, vegetarian, price); if (nums >= MAX_SIZE) { System.out.println("菜单满了!老板不做了!"); return; } menuItems[nums++] = menuItem; } public MenuItem[] getMenuItems() { return menuItems; } @Override public MenuIterator iterator() { return new BRestaurantMenuIterator(menuItems); } }
创建菜单迭代器接口类:MenuIterator.java
public interface MenuIterator { // 容器中是否还有元素 boolean hasNext(); // 获得容器中的下一个元素 MenuItem next(); }
创建A饭店的菜单迭代器实现类:ARestaurantMenuIterator.java
public class ARestaurantMenuIterator implements MenuIterator { private ArrayList<MenuItem> menuItems; private Iterator<MenuItem> iterator; public ARestaurantMenuIterator(ArrayList<MenuItem> menuItems) { this.menuItems = menuItems; iterator = menuItems.iterator(); } @Override public boolean hasNext() { return iterator.hasNext(); } @Override public MenuItem next() { return iterator.next(); } }
创建B饭店的菜单迭代器实现类:BRestaurantMenuIterator.java
public class BRestaurantMenuIterator implements MenuIterator { private MenuItem[] menuItems; private int i = 0; public BRestaurantMenuIterator(MenuItem[] menuItems) { this.menuItems = menuItems; } @Override public boolean hasNext() { return menuItems != null && i < menuItems.length && menuItems[i] != null; } @Override public MenuItem next() { return menuItems[i++]; } }
创建服务员类:Waitress.java
public class Waitress { /** 服务员打印菜单 */ public void printMenu(Menu... menus) { for (Menu menu : menus) { print(menu.iterator()); } } private void print(MenuIterator iterator) { MenuItem menuItem; while (iterator.hasNext()) { menuItem = iterator.next(); System.out.println(String.format("name=%s, desc=%s, price=%s", menuItem.getName(), menuItem.getDesc(), menuItem.getPrice())); } } }
创建测试类:IteratorTest.java
public class IteratorTest { public static void main(String[] args) { /** 构建A餐馆和B餐馆的菜单 */ ARestaurantMenu aMenu = new ARestaurantMenu(); BRestaurantMenu bMenu = new BRestaurantMenu(); /** 构建女服务员 */ Waitress waitress = new Waitress(); /** 将A餐馆和B餐馆的菜单传给服务员,让她报出菜单来 */ waitress.printMenu(aMenu, bMenu); } }
今天的文章内容就这些了:
写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享 。
更多技术干货,欢迎大家关注公众号“爪哇缪斯” ~ \(^o^)/ ~ 「干货分享,每天更新」