〇、小故事
在一座小镇上,有两家特别有名气的小店,一家是远近闻名的早餐店 ,它家的早餐特别好吃,每天早上都能排起长长的队伍;另一家是个蛋糕店,他家是专门从法国请来的蛋糕师傅,蛋糕的香味真是香飘万里。
自从听说这个酱香拿铁 销量非常高之后,这两家店的老板们就觉得强强联合才是能让小店更进一步的关键,所以,两家老板打算合并起来一起做生意。
但是呢,早餐店的菜单是ArrayList维护的,蛋糕店的菜单是数组维护的 。那么对于服务员来说,他报菜单的时候,既要针对ArrayList
类型的菜单进行遍历输出菜品,又需要再针对数组
进行遍历输出菜品。并且,如果后面合并的小店越来越多,菜单用了其他的数据结构存储怎么办呢? 如果强制所有的饭店都使用统一的集合类型去存储菜单的话,那么对小店来说,所有用到旧菜单的地方都需要代码修改。这样改动太大了呀。
为了解决这个问题,我们统一提供了迭代器接口,每个饭店的菜单都要实现迭代器这个接口。那么这就是今天要给大家介绍的设计模式------迭代器模式。
一、模式定义
迭代器模式 (Iterator Pattern
)
提供一个方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部的表示。
二、模式类图
针对上面两个小店合并后菜单类型不一致导致的遍历问题,我们来看一下如何采用迭代模式来解决。首先,我们要创建菜单接口类Menu ,以及两个饭店的菜单实现类,分别是:ARestaurantMenu 和BRestaurantMenu 。其次,创建菜单迭代器接口MenuIterator和两个饭店的菜单迭代器实现类,分别是:ARestaurantMenuIterator 和BRestaurantMenuIterator 。最后,创建服务员类Waitress 和菜单项类MenuItem。具体类图请见如下所示:
三、代码实现
创建菜单明细项 :MenuItem.java
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
java
public interface Menu {
MenuIterator iterator(); // 获得迭代器
}
创建A饭店菜单实现类 :ARestaurantMenu.java
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
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
java
public interface MenuIterator {
// 容器中是否还有元素
boolean hasNext();
// 获得容器中的下一个元素
MenuItem next();
}
创建A饭店的菜单迭代器实现类 :ARestaurantMenuIterator.java
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
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
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
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^)/ ~ 「干货分享,每天更新」