有许多种方法可以把对象堆起来成为一个集合
好消息,当地的餐厅和煎饼屋合并了,但是两者实现的方式却不同,这就造成了分歧。让我们一起去看看把。
一个使用ArrayList集合,另一个使用数组实现,事情看起来确实棘手,我们创建一个女招待作为中间人来使用两个菜单的客户代码
这里就有个问题,我们在打印早餐和午餐的时候由于使用对象不同,Arraylist和数组,这样我们就要写两个for循环了,倘若后面还有新的对象加进来做晚餐呢?或许我们能想出一个办法,让他们的菜单实现一个相同的接口,我们是否可以试着封装多个遍历呢?步骤图如下
OK,看来迭代器模式帮助了我们,迭代器(iterator)依赖于迭代器接口。相关类图如下
想要在餐厅菜单中加入迭代器,我们先定义迭代器接口
package MenuItem;
/**
* 迭代器接口
*
* @author Joy
*
*/
public interface Iterator {
// 知道是否还有更多元素
boolean hasNext();
// 返回下一个元素
Object next();
}
然后先用DinerMenuIterator类去实现接口
package MenuItem;
/**
* 实现迭代器
*
* @author Joy
*
*/
public class DinerMenuIterator implements Iterator {
MenuItem[] items;
int position = 0;// 数组索引
// 构造器初始化传入一个菜单项的数组当参数
public DinerMenuIterator(MenuItem[] items) {
this.items = items;
}
// 返回数组下一项,索引自+1
@Override
public Object next() {
MenuItem menuItem = items[position];
position += 1;
return menuItem;
}
// 判断数组是否满了
@Override
public boolean hasNext() {
if (position >= items.length || items[position] == null) {
return false;
}
return true;
}
}
我们有了菜单迭代器,利用它改写餐厅菜单,DineMenu类中这样写
package MenuItem;
/**
* 对象村餐厅
*
* @author Joy
*
*/
public class DineMenu {
// 菜单总数
static final int MAX_ITEMS = 6;
// 菜单量
int numberOfItems = 0;
MenuItem[] menuItems;
// 初始化数组,添加菜单内容
public DineMenu() {
menuItems = new MenuItem[MAX_ITEMS];
addItem("素食BLT", "(煎)培根、生菜&西红柿并用面包做", true, 2.99);
addItem("BLT", "培根、生菜&西红柿", false, 2.99);
addItem("例汤", "一碗例汤、配土豆沙拉", false, 3.29);
addItem("热狗", "热狗、酸菜、上盖芝士", false, 3.29);
addItem("清蒸时蔬加糙米", "清蒸的蔬菜配糙米", false, 3.05);
}
// 创建一个添加菜单方法
public void addItem(String name, String description, boolean vegetarian,
double price) {
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
if (numberOfItems >= MAX_ITEMS) {
System.out.println("抱歉,菜单已满,不能添加菜单了");
} else {
// 菜单还没满还可以继续添加
menuItems[numberOfItems] = menuItem;
numberOfItems += 1;
}
}
// 使用迭代器遍历菜单
public Iterator createIterator() {
return new DinerMenuIterator(menuItems);
}
}
完整代码如下
迭代器接口
package MenuItem;
/**
* 迭代器接口
*
* @author Joy
*
*/
public interface Iterator {
// 知道是否还有更多元素
boolean hasNext();
// 返回下一个元素
Object next();
}
菜单类
package MenuItem;
/**
* 对象村餐厅
*
* @author Joy
*
*/
public class DineMenu {
// 菜单总数
static final int MAX_ITEMS = 6;
// 菜单量
int numberOfItems = 0;
MenuItem[] menuItems;
// 初始化数组,添加菜单内容
public DineMenu() {
menuItems = new MenuItem[MAX_ITEMS];
addItem("素食BLT", "(煎)培根、生菜&西红柿并用面包做", true, 2.99);
addItem("BLT", "培根、生菜&西红柿", false, 2.99);
addItem("例汤", "一碗例汤、配土豆沙拉", false, 3.29);
addItem("热狗", "热狗、酸菜、上盖芝士", false, 3.29);
addItem("清蒸时蔬加糙米", "清蒸的蔬菜配糙米", false, 3.05);
}
// 创建一个添加菜单方法
public void addItem(String name, String description, boolean vegetarian,
double price) {
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
if (numberOfItems >= MAX_ITEMS) {
System.out.println("抱歉,菜单已满,不能添加菜单了");
} else {
// 菜单还没满还可以继续添加
menuItems[numberOfItems] = menuItem;
numberOfItems += 1;
}
}
// 使用迭代器遍历菜单
public Iterator createIterator() {
return new DinerMenuIterator(menuItems);
}
}
餐厅的实现以及接口
package MenuItem;
/**
* 实现迭代器
*
* @author Joy
*
*/
public class DinerMenuIterator implements Iterator {
MenuItem[] items;
int position = 0;// 数组索引
// 构造器初始化传入一个菜单项的数组当参数
public DinerMenuIterator(MenuItem[] items) {
this.items = items;
}
// 返回数组下一项,索引自+1
@Override
public Object next() {
MenuItem menuItem = items[position];
position += 1;
return menuItem;
}
// 判断数组是否满了
@Override
public boolean hasNext() {
if (position >= items.length || items[position] == null) {
return false;
}
return true;
}
}
package MenuItem;
/**
* 对象村餐厅
*
* @author Joy
*
*/
public class DineMenu {
// 菜单总数
static final int MAX_ITEMS = 6;
// 菜单量
int numberOfItems = 0;
MenuItem[] menuItems;
// 初始化数组,添加菜单内容
public DineMenu() {
menuItems = new MenuItem[MAX_ITEMS];
addItem("素食BLT", "(煎)培根、生菜&西红柿并用面包做", true, 2.99);
addItem("BLT", "培根、生菜&西红柿", false, 2.99);
addItem("例汤", "一碗例汤、配土豆沙拉", false, 3.29);
addItem("热狗", "热狗、酸菜、上盖芝士", false, 3.29);
addItem("清蒸时蔬加糙米", "清蒸的蔬菜配糙米", false, 3.05);
}
// 创建一个添加菜单方法
public void addItem(String name, String description, boolean vegetarian,
double price) {
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
if (numberOfItems >= MAX_ITEMS) {
System.out.println("抱歉,菜单已满,不能添加菜单了");
} else {
// 菜单还没满还可以继续添加
menuItems[numberOfItems] = menuItem;
numberOfItems += 1;
}
}
// 使用迭代器遍历菜单
public Iterator createIterator() {
return new DinerMenuIterator(menuItems);
}
}
同理煎饼屋的实现和接口
package MenuItem;
import java.util.ArrayList;
public class PancakeHouseIterator implements Iterator {
ArrayList items;
int position = 0;
public PancakeHouseIterator(ArrayList items) {
this.items = items;
}
@Override
public Object next() {
Object obj = items.get(position);
position += 1;
return obj;
}
@Override
public boolean hasNext() {
if (position >= items.size()) {
return false;
}
return true;
}
}
package MenuItem;
import java.util.ArrayList;
/**
* 对象村煎饼屋菜单
*
* @author Joy
*
*/
public class PancakeHouseMenu {
ArrayList menuItems;
public PancakeHouseMenu() {
menuItems = new ArrayList();
addItem("K&B薄煎饼早餐", "薄煎饼,清蛋和吐司", true, 2.99);
addItem("薄煎饼早餐例餐", "薄煎饼,煎蛋和香肠", false, 2.99);
addItem("蓝莓薄煎饼", "新鲜蓝莓和蓝莓糖浆做成的薄煎饼", false, 3.49);
addItem("松饼", "可以选择蓝莓或草莓", true, 3.59);
}
// 创建一个添加菜单方法
public void addItem(String name, String description, boolean vegetarian,
double price) {
// 菜单项对象,并加入到ArrayList里
MenuItem menuItem = new MenuItem(name, description, vegetarian, price);
menuItems.add(menuItem);
}
//使用迭代器遍历菜单
public Iterator createIterator(){
return new PancakeHouseIterator(menuItems);
}
}
女招待的实现
package MenuItem;
/**
* 对象村的女招待
*
* @author Joy
*
*/
public class Waitress {
//创建两个餐厅对象的引用
PancakeHouseMenu pancakeHouseMenu;
DineMenu dineMenu;
// 初始化两个菜单
public Waitress(PancakeHouseMenu pancakeHouseMenu, DineMenu dineMenu) {
this.dineMenu = dineMenu;
this.pancakeHouseMenu = pancakeHouseMenu;
}
public void printMenu() {
// 为每一个菜单创建一个迭代器
Iterator pancakeitIterator = pancakeHouseMenu.createIterator();
Iterator dinerIterator = dineMenu.createIterator();
System.out.println("Menu\n=======\nBreakFast");
// 调用下面重载的方法
printMenus(pancakeitIterator);
System.out.println("\nLunch");
// 调用下面重载的方法
printMenus(dinerIterator);
}
// 重载一个printMenu()方法
// 使用迭代器(一次循环即可)来遍历菜单项并打印出来,只调用Iterator接口
public void printMenus(Iterator iterator) {
while (iterator.hasNext()) {
// 取得下一项
MenuItem menuItem = (MenuItem) iterator.next();
System.out.print(menuItem.getName() + ", ");
System.out.print(menuItem.getPrice() + ", ");
System.out.println(menuItem.getDescription());
}
}
}
测试类
package TestMain;
import MenuItem.DineMenu;
import MenuItem.PancakeHouseMenu;
import MenuItem.Waitress;
public class MenuTestDrive {
public static void main(String[] args) {
PancakeHouseMenu pancakeHouseMenu = new PancakeHouseMenu();
DineMenu dineMenu = new DineMenu();
/**
*两个菜单都实现一样的方法,但是并没有实现相同的接口,
*女招待还是要依赖两个具体实现的菜单类
*后面就要修改这里
*
*/
Waitress waitress = new Waitress(pancakeHouseMenu, dineMenu);
waitress.printMenu();
}
}
效果图如下
很巧妙的将两者迭代取出来了。但两者实现的接口却完全一样,这里其实还可以抽象出来成一个共同接口。
感谢你看到这里,迭代器模式上部分到这里就结束了,本人文笔随便,若有不足或错误之处望给予指点,90度弯腰~~~很快我会补全这个内容,生命不息,编程不止!
参考书籍《Head First设计模式》
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。